Skip to content

Update next branch from main patch#1245

Merged
Crunchyman-ralph merged 17 commits intonextfrom
ralph/chore/update.from.main
Sep 24, 2025
Merged

Update next branch from main patch#1245
Crunchyman-ralph merged 17 commits intonextfrom
ralph/chore/update.from.main

Conversation

@Crunchyman-ralph
Copy link
Collaborator

@Crunchyman-ralph Crunchyman-ralph commented Sep 24, 2025

What type of PR is this?

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

Description

Related Issues

How to Test This

# Example commands or steps

Expected result:

Contributor Checklist

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

Changelog Entry


For Maintainers

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

Summary by CodeRabbit

  • Bug Fixes
    • Zed settings now mark task-master-ai as source “custom” for proper recognition.
    • Duplicate “missing config” warnings are suppressed within a single run.
    • CLI version display uses an embedded build version, falling back to “unknown” if unavailable.
  • Chores
    • Version bumps across packages; extension depends on task-master-ai 0.27.1.
    • Build now copies from assets (not public); tests aligned.
  • Documentation
    • Changelogs updated with latest versions and patch notes.

@changeset-bot
Copy link

changeset-bot bot commented Sep 24, 2025

⚠️ No Changeset found

Latest commit: 949f091

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 Sep 24, 2025

Walkthrough

The PR updates version sourcing to use TM_PUBLIC_VERSION, exposes compareVersions from the CLI, adjusts CLI command initialization and banner logic, tweaks config path warning behavior, switches build copy from public to assets, updates tests accordingly, and bumps versions/changelogs. Also adds a Zed profile post-conversion source flag.

Changes

Cohort / File(s) Summary
Versioning and env injection
tsdown.config.ts, apps/cli/src/utils/auto-update.ts, scripts/modules/commands.js
Inject TM_PUBLIC_VERSION at build time; read version from env in auto-update and CLI; default to 'unknown' on failure; export compareVersions.
CLI exports
apps/cli/src/index.ts
Re-export compareVersions alongside existing auto-update utilities.
CLI init and banner
scripts/modules/commands.js
Instantiate new Command("task-master"); skip banner for init; adjust version handling to env-based.
Config path warnings
src/utils/path-utils.js
Emit “missing config” warning once per projectRoot per run using a Set guard.
Zed profile tweak
src/profiles/zed.js
After transform, set context_servers['task-master-ai'].source = 'custom' when present.
Build assets path
tsdown.config.ts, tests/integration/profiles/*
Change copy target from public to assets; update tests to expect assets paths.
Init script asset loading
scripts/init.js
Replace __dirname-based gitignore path with readAsset resolver.
Tests updates
tests/unit/commands.test.js, tests/integration/profiles/roo-files-inclusion.test.js, tests/integration/profiles/rules-files-inclusion.test.js
Align tests with env-based versioning, use @tm/cli compareVersions, and new assets paths.
Version bumps and changelogs
package.json, apps/extension/package.json, apps/docs/package.json, CHANGELOG.md, apps/*/CHANGELOG.md, packages/*/CHANGELOG.md
Bump versions and add changelog entries; extension depends on task-master-ai@0.27.1; docs to 0.0.4; add -rc sections; some “null” headings added.
Changeset cleanup
.changeset/fluffy-clocks-cross.md
Remove a specific changeset entry.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User
  participant CLI as CLI (commands.js)
  participant Build as Build (tsdown.config)
  participant Auto as Auto-Update Utils
  Note over Build: Build-time<br/>- Read package.json.version<br/>- Set env TM_PUBLIC_VERSION<br/>- Copy assets/
  User->>CLI: Execute command
  CLI->>CLI: Instantiate Command("task-master")
  CLI->>CLI: version = process.env.TM_PUBLIC_VERSION || 'unknown'
  alt command != init
    CLI->>User: Display banner (skipped for init)
  end
  CLI->>Auto: checkForUpdate() / compareVersions()
  Auto->>Auto: getCurrentVersion() from TM_PUBLIC_VERSION<br/>fallback '0.0.0' with warn
  Auto-->>CLI: Update decision
  CLI-->>User: Run command flow
Loading
sequenceDiagram
  autonumber
  participant Tool as Tooling
  participant Paths as path-utils
  Note over Paths: findConfigPath()<br/>Warn at most once per projectRoot per run
  Tool->>Paths: Resolve config path
  alt first miss for projectRoot
    Paths->>Tool: Warn and return null
  else subsequent misses
    Paths-->>Tool: Return null (no duplicate warn)
  end
Loading
sequenceDiagram
  autonumber
  participant Profile as Zed Profile
  participant FS as Filesystem
  Profile->>FS: Read MCP config
  Profile->>Profile: Convert to Zed format
  alt context_servers['task-master-ai'] exists
    Profile->>Profile: Set source = "custom"
  end
  Profile->>FS: Write transformed config
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • eyaltoledano

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The title “Update next branch from main patch” is vague and does not clearly summarize the primary change, which appears to be merging a patch release from main (including version bumps, changelog updates, and API exports) into the next branch. It lacks specificity around the actual content or version number being updated, making it hard for someone scanning history to grasp the intent. Please revise the title to explicitly reflect the merge of patch release changes from main into next, including the specific version number (for example, “Merge main into next for v0.27.1 patch release”) so that the purpose and scope of the update are immediately clear.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ralph/chore/update.from.main

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

@Crunchyman-ralph Crunchyman-ralph merged commit 9b7b2ca into next Sep 24, 2025
10 of 11 checks passed
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: 11

Caution

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

⚠️ Outside diff range comments (3)
src/profiles/zed.js (1)

133-141: Bug: early return skips setting source=custom for existing Zed configs

If settings.json is already in Zed format, the early return prevents adding source: "custom". Ensure we apply/ensure the flag and write back in both cases.

Apply this diff:

-		// Check if it's already in Zed format (has context_servers)
-		if (mcpConfig['context_servers']) {
-			log(
-				'info',
-				'[Zed] settings.json already in Zed format, skipping transformation'
-			);
-			return;
-		}
-
-		// Transform to Zed format
-		const zedConfig = transformToZedFormat(mcpConfig);
+		// Prepare Zed config (either already Zed or transformed)
+		const alreadyZed = !!mcpConfig['context_servers'];
+		const zedConfig = alreadyZed ? mcpConfig : transformToZedFormat(mcpConfig);
 
-		// Add "source": "custom" to task-master-ai server for Zed
-		if (
-			zedConfig['context_servers'] &&
-			zedConfig['context_servers']['task-master-ai']
-		) {
-			zedConfig['context_servers']['task-master-ai'].source = 'custom';
-		}
+		// Ensure "source": "custom" on task-master-ai server for Zed (idempotent)
+		const tma = zedConfig?.context_servers?.['task-master-ai'];
+		if (tma && typeof tma === 'object' && !Array.isArray(tma) && tma.source !== 'custom') {
+			zedConfig.context_servers['task-master-ai'] = { ...tma, source: 'custom' };
+		}
 
 		// Write back the transformed config with proper formatting
 		fs.writeFileSync(
 			mcpConfigPath,
 			JSON.stringify(zedConfig, null, '\t') + '\n'
 		);
-
-		log('info', '[Zed] Transformed settings.json to Zed format');
-		log('debug', '[Zed] Renamed mcpServers to context_servers');
+		if (alreadyZed) {
+			log('info', "[Zed] Updated settings.json (ensured source='custom').");
+		} else {
+			log('info', '[Zed] Transformed settings.json to Zed format');
+			log('debug', '[Zed] Renamed mcpServers to context_servers');
+		}

Also applies to: 145-157

apps/cli/src/utils/auto-update.ts (1)

38-60: Fix semver prerelease ordering.

String compare of prerelease tags is incorrect for cases like rc.10 vs rc.2. Implement proper SemVer prerelease comparison (numeric identifiers vs alphanumeric).

Apply this diff:

-export function compareVersions(v1: string, v2: string): number {
-  const toParts = (v: string) => {
-    const [core, pre = ''] = v.split('-', 2);
-    const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0);
-    return { nums, pre };
-  };
-
-  const a = toParts(v1);
-  const b = toParts(v2);
-  const len = Math.max(a.nums.length, b.nums.length);
-
-  // Compare numeric parts
-  for (let i = 0; i < len; i++) {
-    const d = (a.nums[i] || 0) - (b.nums[i] || 0);
-    if (d !== 0) return d < 0 ? -1 : 1;
-  }
-
-  // Handle pre-release comparison
-  if (a.pre && !b.pre) return -1; // prerelease < release
-  if (!a.pre && b.pre) return 1; // release > prerelease
-  if (a.pre === b.pre) return 0; // same or both empty
-  return a.pre < b.pre ? -1 : 1; // basic prerelease tie-break
-}
+export function compareVersions(v1: string, v2: string): number {
+  const parse = (v: string) => {
+    const [core, pre = ''] = v.split('-', 2);
+    const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0);
+    const preParts = pre
+      ? pre.split('.').map((p) => (/^\d+$/.test(p) ? Number.parseInt(p, 10) : p))
+      : [];
+    return { nums, preParts, hasPre: pre.length > 0 };
+  };
+
+  const a = parse(v1);
+  const b = parse(v2);
+
+  // Compare numeric core
+  const len = Math.max(a.nums.length, b.nums.length);
+  for (let i = 0; i < len; i++) {
+    const d = (a.nums[i] || 0) - (b.nums[i] || 0);
+    if (d !== 0) return d < 0 ? -1 : 1;
+  }
+
+  // Handle release vs prerelease
+  if (!a.hasPre && !b.hasPre) return 0;
+  if (a.hasPre && !b.hasPre) return -1;
+  if (!a.hasPre && b.hasPre) return 1;
+
+  // Compare prerelease identifiers
+  const plen = Math.max(a.preParts.length, b.preParts.length);
+  for (let i = 0; i < plen; i++) {
+    const ai = a.preParts[i];
+    const bi = b.preParts[i];
+    if (ai === undefined) return -1; // shorter has lower precedence
+    if (bi === undefined) return 1;
+    const aNum = typeof ai === 'number';
+    const bNum = typeof bi === 'number';
+    if (aNum && bNum) {
+      if (ai !== bi) return ai < bi ? -1 : 1;
+      continue;
+    }
+    if (aNum && !bNum) return -1; // nums < strings
+    if (!aNum && bNum) return 1;  // strings > nums
+    if (ai !== bi) return (ai as string) < (bi as string) ? -1 : 1;
+  }
+  return 0;
+}
tests/unit/commands.test.js (1)

284-288: Avoid importing TS source via .js extension.

auto-update.ts lives under src; importing '../../apps/cli/src/utils/auto-update.js' may break in Jest. Prefer importing from @tm/cli or extensionless path with Jest TS transform.

You can change to:

const cliModule = await import('@tm/cli');
const { displayUpgradeNotification } = cliModule;

or configure Jest to resolve TS and use:

const cliModule = await import('../../apps/cli/src/utils/auto-update.ts');
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32c2b03 and 949f091.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (20)
  • .changeset/fluffy-clocks-cross.md (0 hunks)
  • CHANGELOG.md (1 hunks)
  • apps/cli/CHANGELOG.md (1 hunks)
  • apps/cli/src/index.ts (1 hunks)
  • apps/cli/src/utils/auto-update.ts (2 hunks)
  • apps/docs/CHANGELOG.md (1 hunks)
  • apps/docs/package.json (1 hunks)
  • apps/extension/CHANGELOG.md (1 hunks)
  • apps/extension/package.json (2 hunks)
  • package.json (1 hunks)
  • packages/build-config/CHANGELOG.md (1 hunks)
  • packages/tm-core/CHANGELOG.md (1 hunks)
  • scripts/init.js (1 hunks)
  • scripts/modules/commands.js (3 hunks)
  • src/profiles/zed.js (1 hunks)
  • src/utils/path-utils.js (1 hunks)
  • tests/integration/profiles/roo-files-inclusion.test.js (1 hunks)
  • tests/integration/profiles/rules-files-inclusion.test.js (2 hunks)
  • tests/unit/commands.test.js (2 hunks)
  • tsdown.config.ts (2 hunks)
💤 Files with no reviewable changes (1)
  • .changeset/fluffy-clocks-cross.md
🧰 Additional context used
📓 Path-based instructions (17)
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
**/*.js

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

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

Files:

  • src/utils/path-utils.js
  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
  • src/profiles/zed.js
  • scripts/init.js
  • scripts/modules/commands.js
  • tests/unit/commands.test.js
{src/utils/**,src/middleware/**}

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

Test coverage for all code should meet or exceed 80% lines/functions and 70% branches globally; critical code (utils, middleware) should meet higher thresholds (90% utils, 85% middleware)

Files:

  • src/utils/path-utils.js
tests/{unit,integration,e2e,fixtures}/**/*.js

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

Test files must be organized as follows: unit tests in tests/unit/, integration tests in tests/integration/, end-to-end tests in tests/e2e/, and test fixtures in tests/fixtures/.

Files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
  • tests/unit/commands.test.js
**/*.{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:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
  • tests/unit/commands.test.js
**/*.test.js

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

**/*.test.js: Never use asynchronous operations in tests. Make all mocks return synchronous values when possible.
Always mock tests properly based on the way the tested functions are defined and used.
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.
Use fixtures from tests/fixtures/ for consistent sample data across tests.
Always declare mocks before importing the modules being tested in Jest test files.
Use jest.spyOn() after imports to create spies on mock functions and reference these spies in test assertions.
When testing functions with callbacks, get the callback from your mock's call arguments, execute it directly with test inputs, and verify the results.
For ES modules, use jest.mock() before static imports and jest.unstable_mockModule() before dynamic imports to mock dependencies.
Reset mock functions (mockFn.mockReset()) before dynamic imports if they might have been called previously.
When verifying console assertions, assert against the actual arguments passed (single formatted string), not multiple arguments.
Use mock-fs to mock file system operations in tests, and restore the file system after each test.
Mock API calls (e.g., Anthropic/Claude) by mocking the entire module and providing predictable responses.
Set mock environment variables in test setup and restore them after each test.
Maintain test fixtures separate from test logic.
Follow the mock-first-then-import pattern for all Jest mocks.
Do not define mock variables before jest.mock() calls (they won't be accessible due to hoisting).
Use test-specific file paths (e.g., 'test-tasks.json') for all file operations in tests.
Mock readJSON and writeJSON to avoid real file system interactions in tests.
Verify file operations use the correct paths in expect statements.
Use different file paths for each test to avoid test interdependence.
Verify modifications on the in-memory task objects passed to w...

Files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
  • tests/unit/commands.test.js
tests/integration/**/*.test.js

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

Integration tests must be located in tests/integration/, test interactions between modules, and focus on component interfaces rather than implementation details.

Files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
tests/{unit,integration,e2e}/**/*.test.js

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

tests/{unit,integration,e2e}/**/*.test.js: When testing CLI commands built with Commander.js, test the command action handlers directly rather than trying to mock the entire Commander.js chain.
When mocking the Commander.js chain, mock ALL chainable methods (option, argument, action, on, etc.) and return this (or the mock object) from all chainable method mocks.
Explicitly handle all options, including defaults and shorthand flags (e.g., -p for --prompt), and include null/undefined checks in test implementations for parameters that might be optional.
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.
Mock the action handlers for CLI commands and verify they're called with correct arguments.
Use sample task fixtures for consistent test data, mock file system operations, and test both success and error paths for task operations.
Mock console output and verify correct formatting in UI function tests. Use flexible assertions like toContain() or toMatch() for formatted output.
Mock chalk functions to return the input text to make testing easier while still verifying correct function calls.

Files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
  • tests/unit/commands.test.js
tests/{integration,e2e}/**/*.test.js

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

Properly mock session objects when required by functions, and reset environment variables between tests if modified.

Files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
**/*.{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:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
  • tests/unit/commands.test.js
tests/{unit,integration,e2e}/**

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

Organize test directories by test type (unit, integration, e2e) and mirror source structure where possible

Files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
  • tests/unit/commands.test.js
scripts/modules/commands.js

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

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

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

Files:

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

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

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

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

Files:

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

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

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

Files:

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

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

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

Files:

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

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

Each module should have a corresponding unit test file in tests/unit/ that reflects the module structure (one test file per module).

Files:

  • tests/unit/commands.test.js
tests/unit/**/*.test.js

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

tests/unit/**/*.test.js: Unit tests must be located in tests/unit/, test individual functions and utilities in isolation, mock all external dependencies, and keep tests small, focused, and fast.
Do not include actual command execution in unit tests.

Files:

  • tests/unit/commands.test.js
🧠 Learnings (69)
📓 Common learnings
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: packages/tm-core/src/auth/config.ts:5-7
Timestamp: 2025-09-02T21:51:27.921Z
Learning: The user Crunchyman-ralph prefers not to use node: scheme imports (e.g., 'node:os', 'node:path') for Node.js core modules and considers suggestions to change bare imports to node: scheme as too nitpicky.
📚 Learning: 2025-07-18T17:10:12.881Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dev_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:12.881Z
Learning: For CLI usage, install Taskmaster globally with `npm install -g task-master-ai` or use locally via `npx task-master-ai ...`.

Applied to files:

  • package.json
  • apps/extension/package.json
  • scripts/modules/commands.js
📚 Learning: 2025-09-24T15:12:12.593Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.593Z
Learning: Use the task-master CLI instead of node scripts/dev.js; all functionality is available via task-master <command> and accepts the same options

Applied to files:

  • package.json
  • scripts/modules/commands.js
📚 Learning: 2025-08-11T12:30:23.843Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-11T12:30:23.843Z
Learning: Import Task Master's development workflow commands and guidelines; treat the contents of ./.taskmaster/CLAUDE.md as if included in the main CLAUDE.md

Applied to files:

  • apps/extension/CHANGELOG.md
  • CHANGELOG.md
📚 Learning: 2025-09-22T19:45:13.301Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1232
File: packages/build-config/package.json:14-15
Timestamp: 2025-09-22T19:45:13.301Z
Learning: In the eyaltoledano/claude-task-master repository, Crunchyman-ralph intentionally omits version fields from internal packages (like tm/build-config) to prevent changesets from releasing new versions for these packages. This is the desired behavior for internal tooling packages that should not be published or versioned independently.

Applied to files:

  • apps/extension/CHANGELOG.md
  • CHANGELOG.md
📚 Learning: 2025-09-22T19:45:04.246Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1232
File: packages/tm-core/package.json:50-51
Timestamp: 2025-09-22T19:45:04.246Z
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/extension/CHANGELOG.md
  • apps/cli/src/utils/auto-update.ts
  • CHANGELOG.md
  • apps/extension/package.json
📚 Learning: 2025-07-18T17:07:53.100Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/changeset.mdc:0-0
Timestamp: 2025-07-18T17:07:53.100Z
Learning: Applies to .changeset/*.md : When running `npm run changeset` or `npx changeset add`, provide a concise summary of the changes for the `CHANGELOG.md` in imperative mood, typically a single line, and not a detailed Git commit message.

Applied to files:

  • apps/cli/CHANGELOG.md
📚 Learning: 2025-07-18T17:13:11.229Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/self_improve.mdc:0-0
Timestamp: 2025-07-18T17:13:11.229Z
Learning: Document breaking changes

Applied to files:

  • apps/cli/CHANGELOG.md
  • packages/build-config/CHANGELOG.md
📚 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:

  • src/utils/path-utils.js
📚 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 : Verify file operations use the correct paths in expect statements.

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
📚 Learning: 2025-09-24T15:12:12.593Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.593Z
Learning: Applies to assets/**/.windsurfrules : Keep examples synchronized with code, update external references, maintain links, and document breaking changes in the rules

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
📚 Learning: 2025-09-24T15:12:12.593Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.593Z
Learning: Applies to assets/**/.windsurfrules : Maintain rules by updating for new patterns, adding real code examples, removing outdated patterns, and cross-referencing related rules

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
📚 Learning: 2025-09-24T15:12:12.593Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.593Z
Learning: Applies to assets/**/.windsurfrules : Modify existing rules when better examples exist, new edge cases are found, related rules change, or implementation details evolve

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
📚 Learning: 2025-09-24T15:12:12.593Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.593Z
Learning: Applies to assets/**/.windsurfrules : Analyze new code against existing rules, identify standardizable patterns, check error handling and tests, and reference external docs when enhancing rules

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Test core logic independently with both data formats, mock file system operations, test tag resolution behavior, and verify migration compatibility in unit tests.

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
  • tests/unit/commands.test.js
📚 Learning: 2025-09-24T15:12:12.593Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.593Z
Learning: Applies to assets/**/.windsurfrules : Deprecate outdated patterns, remove rules that no longer apply, update references, and document migration paths

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
📚 Learning: 2025-09-24T15:12:12.593Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.593Z
Learning: Applies to assets/**/.windsurfrules : Add new rules when technologies/patterns appear in 3+ files, bugs can be prevented, repeated review feedback occurs, or new security/performance patterns emerge

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
📚 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 : Use test-specific file paths (e.g., 'test-tasks.json') for all file operations in tests.

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
📚 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:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
  • tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to tests/{unit,integration,e2e,fixtures}/**/*.js : Test files must be organized as follows: unit tests in tests/unit/, integration tests in tests/integration/, end-to-end tests in tests/e2e/, and test fixtures in tests/fixtures/.

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
📚 Learning: 2025-08-03T12:13:33.875Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-08-03T12:13:33.875Z
Learning: Applies to **/__tests__/**/*.ts : In JavaScript/TypeScript projects using Jest, test files should be located in __tests__ directories or match *.test.ts and *.spec.ts patterns

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
📚 Learning: 2025-07-18T17:10:31.810Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/git_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:31.810Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx} : Create a test file if needed and ensure all tests pass before completing a task

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
📚 Learning: 2025-08-03T12:13:33.875Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-08-03T12:13:33.875Z
Learning: Applies to tests/{unit,integration,e2e}/** : Organize test directories by test type (unit, integration, e2e) and mirror source structure where possible

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to tests/unit/*.js : Each module should have a corresponding unit test file in tests/unit/ that reflects the module structure (one test file per module).

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
📚 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 : Mock console output and verify correct formatting in UI function tests. Use flexible assertions like toContain() or toMatch() for formatted output.

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/unit/commands.test.js
📚 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/**/*.test.js : Unit tests must be located in tests/unit/, test individual functions and utilities in isolation, mock all external dependencies, and keep tests small, focused, and fast.

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
📚 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/fixtures/**/* : Test fixtures must be located in tests/fixtures/, provide reusable test data, and be exported as named exports for reuse.

Applied to files:

  • tests/integration/profiles/rules-files-inclusion.test.js
  • tests/integration/profiles/roo-files-inclusion.test.js
📚 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 : Implement semantic version comparison and display attractive update notifications using boxen.

Applied to files:

  • apps/cli/src/index.ts
  • apps/cli/src/utils/auto-update.ts
  • tests/unit/commands.test.js
📚 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 : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.

Applied to files:

  • apps/cli/src/index.ts
  • tests/unit/commands.test.js
📚 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 : Integrate version checking in the CLI run function, starting the update check in the background and displaying notifications after command execution.

Applied to files:

  • apps/cli/src/index.ts
  • scripts/modules/commands.js
📚 Learning: 2025-08-12T01:22:48.873Z
Learnt from: olssonsten
PR: eyaltoledano/claude-task-master#1112
File: src/profiles/roo.js:0-0
Timestamp: 2025-08-12T01:22:48.873Z
Learning: In src/profiles/roo.js, the enhanceRooMCPConfiguration function was simplified to only set server.timeout = 300, removing problematic overwrites of server.env and alwaysAllow configurations that could interfere with user settings.

Applied to files:

  • tests/integration/profiles/roo-files-inclusion.test.js
📚 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 : Use mock-fs to mock file system operations in tests, and restore the file system after each test.

Applied to files:

  • tests/integration/profiles/roo-files-inclusion.test.js
📚 Learning: 2025-08-03T12:13:33.875Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-08-03T12:13:33.875Z
Learning: Applies to {tests/setup.ts,tests/setup/integration.ts,tests/teardown.ts} : Test setup files should be created at tests/setup.ts, tests/setup/integration.ts, and tests/teardown.ts

Applied to files:

  • tests/integration/profiles/roo-files-inclusion.test.js
📚 Learning: 2025-09-24T15:12:58.821Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/AGENTS.md:0-0
Timestamp: 2025-09-24T15:12:58.821Z
Learning: Applies to assets/**/.mcp.json : Configure the Task Master MCP server in .mcp.json under mcpServers.task-master-ai using npx task-master-ai and provide required API key env vars

Applied to files:

  • src/profiles/zed.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to mcp-server/src/tools/*.js : Create tool definitions in 'mcp-server/src/tools/', use Zod for parameter validation, include optional tag parameter for multi-context support, and follow established naming conventions.

Applied to files:

  • src/profiles/zed.js
📚 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 : MCP tools must follow a specific structure: use server.addTool with snake_case tool names, define parameters using Zod, and implement the execute function as an async function.

Applied to files:

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

Applied to files:

  • scripts/init.js
  • scripts/modules/commands.js
📚 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:

  • scripts/init.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/utils.js : Use `path.join()` for cross-platform path construction, `path.resolve()` for absolute paths, and validate paths before file operations.

Applied to files:

  • scripts/init.js
📚 Learning: 2025-07-17T21:33:57.585Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1002
File: .changeset/puny-friends-give.md:2-3
Timestamp: 2025-07-17T21:33:57.585Z
Learning: In the eyaltoledano/claude-task-master repository, the MCP server code in mcp-server/src/ is part of the main "task-master-ai" package, not a separate "mcp-server" package. When creating changesets for MCP server changes, use "task-master-ai" as the package name.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-07-31T20:49:04.638Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#997
File: apps/extension/package.publish.json:2-8
Timestamp: 2025-07-31T20:49:04.638Z
Learning: In the eyaltoledano/claude-task-master repository, the VS Code extension uses a 3-file packaging system where package.json (with name "extension") is for development within the monorepo, while package.publish.json (with name "task-master-hamster") contains the clean manifest for VS Code marketplace publishing. The different names are intentional and serve distinct purposes in the build and publishing workflow.

Applied to files:

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

Applied to files:

  • 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-17T19:09:08.882Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1211
File: jest.resolver.cjs:8-15
Timestamp: 2025-09-17T19:09:08.882Z
Learning: In the eyaltoledano/claude-task-master project, the team only uses .ts files and does not plan to use .tsx or .mts extensions, so Jest resolver and build tooling should focus on .js → .ts mapping only.

Applied to files:

  • apps/extension/package.json
📚 Learning: 2025-09-24T15:12:12.594Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.594Z
Learning: Manage dependencies with task-master add-dependency and remove-dependency; validate and fix using validate-dependencies and fix-dependencies

Applied to files:

  • apps/extension/package.json
📚 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:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/utils.js : Place utilities used primarily by the core `task-master` CLI logic and command modules (`scripts/modules/*`) into `scripts/modules/utils.js`.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-09-03T12:15:03.208Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: apps/cli/src/commands/auth.command.ts:222-224
Timestamp: 2025-09-03T12:15:03.208Z
Learning: The CLI can be invoked using both "task-master" and "tm" as aliases - both forms are valid and acceptable in help text, documentation, and examples.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/commands.js : Follow the established pattern in 'commands.js' for CLI command implementation, using Commander.js for argument parsing, including comprehensive help text and examples, and supporting tagged task context awareness.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/commands.js : Use consistent patterns for option naming and help text in CLI commands.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:10:12.881Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dev_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:12.881Z
Learning: Use the Taskmaster command set (`task-master` CLI or MCP tools) for all task management operations: listing, expanding, updating, tagging, and status changes.

Applied to files:

  • scripts/modules/commands.js
📚 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: Guidelines for implementing CLI commands using Commander.js (commands.mdc).

Applied to files:

  • scripts/modules/commands.js
📚 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 : Follow the provided command template structure for all CLI commands using Commander.js, including descriptive command names, option definitions, and async action handlers.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Follow the provided command template structure for all CLI commands using Commander.js, including use of .command(), .description(), .option(), and .action() methods.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/*.js : When implementing project initialization commands, support both CLI and MCP, support non-interactive modes with sensible defaults, handle project metadata, and create necessary files and directories.

Applied to files:

  • scripts/modules/commands.js
📚 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 : When testing CLI commands built with Commander.js, test the command action handlers directly rather than trying to mock the entire Commander.js chain.

Applied to files:

  • tests/unit/commands.test.js
📚 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 : Mock the action handlers for CLI commands and verify they're called with correct arguments.

Applied to files:

  • tests/unit/commands.test.js
📚 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:

  • tests/unit/commands.test.js
📚 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:

  • tests/unit/commands.test.js
📚 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:

  • tests/unit/commands.test.js
📚 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 rely on environment variables for API keys in tests; set mock environment variables in test setup.

Applied to files:

  • tests/unit/commands.test.js
📚 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 : Explicitly handle all options, including defaults and shorthand flags (e.g., -p for --prompt), and include null/undefined checks in test implementations for parameters that might be optional.

Applied to files:

  • tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Test CLI and MCP interfaces with real task data, verify end-to-end workflows across tag contexts, and test error scenarios and recovery in integration tests.

Applied to files:

  • tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Module dependencies should be mocked before importing the test module, following Jest's hoisting behavior.

Applied to files:

  • tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Follow the mock-first-then-import pattern and use jest.spyOn() for testing in Jest, clearing mocks between tests.

Applied to files:

  • tests/unit/commands.test.js
📚 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:

  • tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Mock external libraries (e.g., fs, commander, anthropic-ai/sdk) at the module level in tests.

Applied to files:

  • tests/unit/commands.test.js
📚 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 : When mocking the Commander.js chain, mock ALL chainable methods (option, argument, action, on, etc.) and return this (or the mock object) from all chainable method mocks.

Applied to files:

  • tests/unit/commands.test.js
📚 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: Guidelines for implementing and maintaining tests for Task Master CLI (tests.mdc).

Applied to files:

  • tests/unit/commands.test.js
🧬 Code graph analysis (6)
src/utils/path-utils.js (2)
scripts/modules/task-manager/expand-task.js (1)
  • logger (325-331)
scripts/modules/task-manager/expand-all-tasks.js (1)
  • logger (53-70)
tests/integration/profiles/rules-files-inclusion.test.js (2)
src/utils/profiles.js (1)
  • rulesDir (48-48)
mcp-server/src/core/direct-functions/rules.js (1)
  • rulesDir (135-135)
apps/cli/src/utils/auto-update.ts (1)
apps/cli/src/index.ts (1)
  • compareVersions (22-22)
scripts/init.js (1)
src/utils/asset-resolver.js (1)
  • readAsset (89-92)
tsdown.config.ts (1)
index.js (1)
  • packageJson (37-37)
tests/unit/commands.test.js (1)
index.js (4)
  • program (68-68)
  • packageJson (37-37)
  • version (64-64)
  • version (64-64)
⏰ 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 (15)
apps/extension/CHANGELOG.md (1)

3-23: Changelog entries look consistent.

Entries and versions align with the dependency bump. No issues.

CHANGELOG.md (1)

3-24: Changelog update LGTM.

Comprehensive and consistent with the PR scope; no action needed.

tests/integration/profiles/rules-files-inclusion.test.js (2)

19-22: Switched rules source to assets/rules – OK.

Matches the repo move from public to assets. Ensure tsdown copies assets (see tsdown.config.ts).


89-96: Roo assets path updated – OK.

The new assertions under assets/roocode are correct given the directory move.

scripts/init.js (1)

617-623: Asset-resolver usage for .gitignore — good change.

Reading the template via readAsset and delegating merge logic to manageGitignoreFile is the right abstraction.

tsdown.config.ts (1)

38-39: Copying assets instead of public — OK.

Matches test expectations and asset-resolver usage.

Please verify that all required runtime assets are under assets/ and referenced by asset-resolver/getAssetPath.

tests/unit/commands.test.js (3)

99-100: Using compareVersions from @tm/cli — OK.

Imports the public API as intended by the PR.


117-118: CLI name assertion OK.

Confirms the binary name remains task-master.


141-147: Version fallback mismatch: tests expect 'unknown'.

Current auto-update fallback returns '0.0.0'. After adopting the suggested change to return 'unknown', this test will pass consistently.

scripts/modules/commands.js (1)

6-6: Commander import looks good

ESM import of Command is correct for Commander v12.

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

21-23: Re-exporting compareVersions (and displayUpgradeNotification) is good

This aligns CLI consumers with the update utilities.

Ensure this API addition is noted in the changelog and that compareVersions handles pre-release tags consistently across callers.

package.json (1)

3-3: Version bump aligned with main sync.

Line 3 bumps the root package to 0.27.1, matching the upstream merge cadence. No issues spotted here.

apps/docs/package.json (1)

3-3: Docs package version bump looks good.

Line 3 updates docs to 0.0.4, keeping it in lockstep with the release train. All clear.

apps/docs/CHANGELOG.md (1)

3-4: Changelog header addition acknowledged.

The new 0.0.4 section header slots in cleanly; thanks for keeping the log current.

tests/integration/profiles/roo-files-inclusion.test.js (1)

103-110: Asset path assertions look correct.

Switching the expectations to assets/roocode mirrors the new source layout and keeps the integration check meaningful. 👍

Comment on lines +3 to +8
## null

### Patch Changes

- Updated dependencies []:
- @tm/core@null
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

Fix the null changelog/version placeholder.

The new section renders as ## null and even lists @tm/core@null; that needs to be replaced with the actual version info (or removed) before release.

🤖 Prompt for AI Agents
In apps/cli/CHANGELOG.md around lines 3 to 8 the changelog contains a
placeholder "null" for the release header and dependency version; replace "##
null" with the correct release header (e.g., "## vX.Y.Z") or remove that section
if it's not applicable, and update the dependency line "@tm/core@null" to the
actual published version (or delete the dependency entry) so the changelog
contains a valid version string; also ensure whatever script/tool produced this
file uses the correct version variable so the placeholder does not reappear.

Comment on lines +18 to 30
* Get current version from build-time injected environment variable
*/
function getCurrentVersion(): string {
try {
return packageJson.version;
} catch (error) {
console.warn('Could not read package.json for version info');
return '0.0.0';
// Version is injected at build time via TM_PUBLIC_VERSION
const version = process.env.TM_PUBLIC_VERSION;
if (version && version !== 'unknown') {
return version;
}

// Fallback for development or if injection failed
console.warn('Could not read version from TM_PUBLIC_VERSION, using fallback');
return '0.0.0';
}
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

Align fallback version with runtime expectations and avoid false updates.

Using '0.0.0' as fallback can trigger unnecessary updates in dev and conflicts with tests expecting 'unknown'. Prefer 'unknown' and short-circuit update checks when unknown.

Apply this diff:

-// Version is injected at build time via TM_PUBLIC_VERSION
-const version = process.env.TM_PUBLIC_VERSION;
-if (version && version !== 'unknown') {
-  return version;
-}
-
-// Fallback for development or if injection failed
-console.warn('Could not read version from TM_PUBLIC_VERSION, using fallback');
-return '0.0.0';
+// Version is injected at build time via TM_PUBLIC_VERSION
+const version = process.env.TM_PUBLIC_VERSION;
+if (version && version !== 'unknown') {
+  return version;
+}
+// Fallback for development or if injection failed
+console.warn('Could not read version from TM_PUBLIC_VERSION, using fallback "unknown"');
+return 'unknown';

Additionally, guard checkForUpdate when version is unknown:

 export async function checkForUpdate(
   currentVersionOverride?: string
 ): Promise<UpdateInfo> {
   const currentVersion = currentVersionOverride || getCurrentVersion();
 
+  if (currentVersion === 'unknown') {
+    return {
+      currentVersion,
+      latestVersion: 'unknown',
+      needsUpdate: false,
+    };
+  }
🤖 Prompt for AI Agents
In apps/cli/src/utils/auto-update.ts around lines 18 to 30, the current fallback
returns '0.0.0' which can cause false update checks and conflicts with tests;
change the fallback to return 'unknown' instead of '0.0.0', update the console
message if desired, and then update the checkForUpdate caller (or checkForUpdate
itself) to short-circuit/skip any update checks when the current version equals
'unknown' so no network/update logic runs for unknown versions.

Comment on lines +243 to 244
"task-master-ai": "0.27.1"
},
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

Revert workspace dependency pinning for task-master-ai.

Switching the workspace dependency from "*" to "0.27.1" breaks the intended monorepo flow—npm will now try to resolve a registry tag instead of the local package, which is why we deliberately keep "*" here (as we discussed on prior PRs). Please restore the "*" constraint so the extension continues to consume the in-repo build.

🤖 Prompt for AI Agents
In apps/extension/package.json around lines 243 to 244, the workspace dependency
for "task-master-ai" was changed from "*" to "0.27.1", which forces npm to
resolve from the registry instead of the local monorepo; revert the version
string back to "*" so the package consumes the in-repo workspace build and
restore the previous workspace pinning.

Comment on lines +3 to +4
## null

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

Changelog entry shows up as null.

This heading should be a real version (or be removed) before we merge; publishing a ## null entry will confuse consumers and automated tooling.

🤖 Prompt for AI Agents
In packages/build-config/CHANGELOG.md around lines 3 to 4, the changelog
contains a heading "## null" which must be replaced or removed; change the
heading to a real version (e.g., "## Unreleased" or the proper semantic version
like "## vX.Y.Z") or delete the empty section if there are no entries, and
ensure the file remains valid Markdown with no "null" tokens so automated
tooling and consumers aren't confused.

Comment on lines +3 to +4
## null

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

Invalid ## null changelog section.

We can’t ship a null version header—either populate it with the correct release number or drop the placeholder entirely.

🤖 Prompt for AI Agents
In packages/tm-core/CHANGELOG.md around lines 3 to 4, the changelog contains an
invalid "## null" section header; replace "## null" with the correct release
header (e.g., "## vX.Y.Z - YYYY-MM-DD") or remove the placeholder header
entirely and ensure entries are under a valid version heading so the changelog
contains only proper versioned sections.

Comment on lines +5111 to 5114
// Display banner if not in a pipe (except for init command which has its own banner)
const isInitCommand = argv.includes('init');
if (process.stdout.isTTY && !isInitCommand) {
displayBanner();
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Skip banner for --help/--version too

Avoid noisy output for one-shot flags.

Apply this diff:

- // Display banner if not in a pipe (except for init command which has its own banner)
- const isInitCommand = argv.includes('init');
- if (process.stdout.isTTY && !isInitCommand) {
+ // Display banner if not in a pipe (skip for init/help/version)
+ const isInitCommand = argv.includes('init');
+ const isVersionFlag = argv.includes('-V') || argv.includes('--version');
+ const isHelpFlag = argv.includes('-h') || argv.includes('--help');
+ if (process.stdout.isTTY && !isInitCommand && !isVersionFlag && !isHelpFlag) {
   displayBanner();
 }
🤖 Prompt for AI Agents
In scripts/modules/commands.js around lines 5111 to 5114, the banner is still
shown when users pass one-shot flags like --help or --version; update the check
to skip the banner for those flags as well. Add detection for help/version
(e.g., const isOneShot = argv.includes('--help') || argv.includes('-h') ||
argv.includes('--version') || argv.includes('-v')) and change the conditional to
if (process.stdout.isTTY && !isInitCommand && !isOneShot) so the banner is
suppressed for init, help, and version invocations.

Comment on lines +145 to +151
// Add "source": "custom" to task-master-ai server for Zed
if (
zedConfig['context_servers'] &&
zedConfig['context_servers']['task-master-ai']
) {
zedConfig['context_servers']['task-master-ai'].source = 'custom';
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Type-safety: guard assignment and avoid mutating original object

Harden the assignment to only set source when the entry is a plain object, and prefer creating a new object over mutating the existing one.

Apply this diff (if you keep the current structure):

-		if (
-			zedConfig['context_servers'] &&
-			zedConfig['context_servers']['task-master-ai']
-		) {
-			zedConfig['context_servers']['task-master-ai'].source = 'custom';
-		}
+		const tma = zedConfig?.context_servers?.['task-master-ai'];
+		if (tma && typeof tma === 'object' && !Array.isArray(tma)) {
+			if (tma.source !== 'custom') {
+				zedConfig.context_servers['task-master-ai'] = { ...tma, source: 'custom' };
+			}
+		}
📝 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
// Add "source": "custom" to task-master-ai server for Zed
if (
zedConfig['context_servers'] &&
zedConfig['context_servers']['task-master-ai']
) {
zedConfig['context_servers']['task-master-ai'].source = 'custom';
}
// Add "source": "custom" to task-master-ai server for Zed
const tma = zedConfig?.context_servers?.['task-master-ai'];
if (tma && typeof tma === 'object' && !Array.isArray(tma)) {
if (tma.source !== 'custom') {
zedConfig.context_servers['task-master-ai'] = { ...tma, source: 'custom' };
}
}
🤖 Prompt for AI Agents
In src/profiles/zed.js around lines 145-151, the code unconditionally mutates
zedConfig.context_servers['task-master-ai'] to add source; instead guard that
the entry is a plain non-null object (e.g. typeof entry === 'object' && entry
!== null && !Array.isArray(entry')) and then replace it with a new object rather
than mutating in-place (e.g. assign zedConfig.context_servers['task-master-ai']
= { ...existingEntry, source: 'custom' }) so you only set source for valid
objects and avoid mutating the original object.

Comment on lines +466 to +476
// Only warn once per command execution to prevent spam during init
const warningKey = `config_warning_${projectRoot}`;

if (!global._tmConfigWarningsThisRun) {
global._tmConfigWarningsThisRun = new Set();
}

if (!global._tmConfigWarningsThisRun.has(warningKey)) {
global._tmConfigWarningsThisRun.add(warningKey);
logger.warn?.(`No configuration file found in project: ${projectRoot}`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Avoid coupling this memoization to global

Please keep the warning bookkeeping module-scoped instead of hanging a mutable Set off global. This leaks state across unrelated consumers sharing the process (tests, embedded MCP server, etc.) and violates our JS guideline about declaring globals at module top. A cached Set declared once per module gives the same “warn once per project root” behavior without touching the global namespace.

-	if (!global._tmConfigWarningsThisRun) {
-		global._tmConfigWarningsThisRun = new Set();
-	}
-
-	if (!global._tmConfigWarningsThisRun.has(warningKey)) {
-		global._tmConfigWarningsThisRun.add(warningKey);
+	if (!configWarningsThisRun.has(warningKey)) {
+		configWarningsThisRun.add(warningKey);
 		logger.warn?.(`No configuration file found in project: ${projectRoot}`);
 	}

Add this near the imports:

const configWarningsThisRun = new Set();
🤖 Prompt for AI Agents
In src/utils/path-utils.js around lines 466 to 476, the code memoizes config
warnings on the global object which leaks mutable state across consumers;
instead declare a module-scoped Set near the top of the file and use that for
bookkeeping. Replace references to global._tmConfigWarningsThisRun with the new
module-level Set (e.g., configWarningsThisRun) so the warningKey is added and
checked against that Set, and remove any creation/access of the global property.

Comment on lines +121 to 139
// Read actual version from package.json
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
const expectedVersion = packageJson.version;

const program = setupCLI();
const version = program._version();
expect(mockReadFileSync).toHaveBeenCalledWith('package.json', 'utf8');
expect(version).toBe('1.0.0');
});

test('should use default version when package.json is not available', () => {
mockExistsSync.mockReturnValue(false);
// Set environment variable to match package.json
const originalEnv = process.env.TM_PUBLIC_VERSION;
process.env.TM_PUBLIC_VERSION = expectedVersion;

const program = setupCLI();
const version = program._version();
expect(mockReadFileSync).not.toHaveBeenCalled();
expect(version).toBe('unknown');
const version = program.version();
expect(version).toBe(expectedVersion);

// Restore original environment
if (originalEnv !== undefined) {
process.env.TM_PUBLIC_VERSION = originalEnv;
} else {
delete process.env.TM_PUBLIC_VERSION;
}
});
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

Fix test to read real package.json despite fs mock.

You mocked fs.readFileSync above, so JSON.parse(fs.readFileSync(...)) will fail. Use the real fs for this read.

Apply this diff:

-      const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
+      const realFs = jest.requireActual('fs');
+      const packageJson = JSON.parse(realFs.readFileSync('package.json', 'utf8'));
🤖 Prompt for AI Agents
In tests/unit/commands.test.js around lines 121 to 139, the test attempts to
read package.json using fs.readFileSync but earlier in the test suite fs is
mocked, so JSON.parse will fail; replace that single read with the real
filesystem API by calling the original fs via jest.requireActual('fs') (e.g.,
const realFs = jest.requireActual('fs'); const packageJson =
JSON.parse(realFs.readFileSync('package.json','utf8'))), leaving the rest of the
test and env restore logic unchanged.

Comment on lines +11 to +20
// Inject package.json version at build time
try {
const packageJson = JSON.parse(
require('fs').readFileSync('package.json', 'utf8')
);
envs['TM_PUBLIC_VERSION'] = packageJson.version || 'unknown';
} catch (error) {
console.warn('Could not read package.json version during build:', error);
envs['TM_PUBLIC_VERSION'] = 'unknown';
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick

Prefer ESM fs import in TS config.

Using require in a TS ESM config can break in ESM-only environments. Import fs and use readFileSync directly.

Apply this diff:

-  // Inject package.json version at build time
-  try {
-    const packageJson = JSON.parse(
-      require('fs').readFileSync('package.json', 'utf8')
-    );
+  // Inject package.json version at build time
+  try {
+    import fs from 'fs';
+    const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
     envs['TM_PUBLIC_VERSION'] = packageJson.version || 'unknown';
   } catch (error) {
     console.warn('Could not read package.json version during build:', error);
     envs['TM_PUBLIC_VERSION'] = 'unknown';
   }

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

🤖 Prompt for AI Agents
In tsdown.config.ts around lines 11 to 20, replace the dynamic CommonJS
require('fs') usage with an ESM import (e.g. import fs from 'fs') and call
fs.readFileSync directly inside the existing try/catch; keep the JSON.parse and
fallback logic the same, making sure to update the top of the file to include
the fs import so the file stays ESM-compatible and avoids runtime errors in
ESM-only environments.

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