fix: Add cross-process file locking to prevent race conditions#1566
Conversation
🦋 Changeset detectedLatest commit: 0b05a35 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughImplements cross-process file locking and atomic write semantics for JSON file operations, adds lock utilities (sync/async), updates FileOperations with modifyJson and writer caching, adds proper-lockfile dependency, and introduces comprehensive tests covering concurrency and stale-lock handling. Changes
Sequence Diagram(s)sequenceDiagram
participant ProcA as Process A
participant ProcB as Process B
participant Lock as Lock Manager
participant FS as Filesystem
ProcA->>Lock: Request exclusive lock (tasks.json)
ProcB->>Lock: Request exclusive lock (tasks.json)
Note over Lock: Only one grant at a time
Lock-->>ProcA: Lock granted
Lock-->>ProcB: Waiting
ProcA->>FS: Read tasks.json (inside lock)
FS-->>ProcA: Current data
ProcA->>ProcA: Apply modifier
ProcA->>FS: Write temp file + rename (atomic)
FS-->>ProcA: Write complete
ProcA->>Lock: Release lock
Lock-->>ProcB: Lock granted
ProcB->>FS: Read tasks.json (fresh, includes ProcA changes)
FS-->>ProcB: Current data
ProcB->>ProcB: Apply modifier
ProcB->>FS: Write temp file + rename (atomic)
FS-->>ProcB: Write complete
ProcB->>Lock: Release lock
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 Fix all issues with AI agents
In @.changeset/fix-file-locking.md:
- Line 11: Change the unhyphenated compound adjective "10 second timeout" to the
hyphenated form "10-second timeout" in the changelog entry so the phrase is
grammatically correct.
In
@packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts:
- Around line 55-76: The writeJson implementation acquires a lock but does not
re-read the file inside the lock, which allows lost updates from stale
snapshots; fix by changing the API or adding a new method (e.g.,
writeJsonWithMerge) that after ensureFileExists() and after acquiring the lock
calls readJson(filePath) to get the current state, applies a provided
transformation/update function to that current state, then calls
performAtomicWrite(filePath, updated) before releasing the lock; alternatively,
document that callers must perform the read-merge-write inside the lock and
provide helper lock/unlock utilities (reference writeJson, performAtomicWrite,
readJson, and LOCK_OPTIONS to locate the code).
In @scripts/modules/utils.js:
- Line 124: The synchronous backoff calculation in withFileLockSync is using
Math.pow(1.5, attempt) while the async LOCK_OPTIONS uses a factor of 2, causing
inconsistent retry behavior; update the backoff factor in withFileLockSync to
match LOCK_OPTIONS (use Math.pow(2, attempt)) or vice versa so both code paths
use the same exponential base, and ensure any related comments or tests
referencing the factor are updated to reflect the chosen value.
- Around line 23-33: The retry counts are inconsistent:
LOCK_OPTIONS.retries.retries is 5 but withFileLockSync uses maxRetries = 10; fix
by centralizing the retry count into a single constant (e.g., LOCK_RETRIES) or
derive withFileLockSync’s default from LOCK_OPTIONS.retries.retries, update
withFileLockSync signature to use that shared value, and adjust any
tests/docs/comments to reflect the unified retry policy so async and sync
locking behave consistently (or explicitly document a justified difference if
you intentionally keep them different).
- Around line 42-51: withFileLock currently creates a file containing '{}' which
assumes JSON; change the initialization so it does not corrupt non-JSON files:
detect the target by inspecting filepath (e.g., path.extname(filepath)), create
parent dirs as before, and if extension === '.json' write '{}' to the new file,
otherwise create an empty file ('') and do not assume content; keep the rest of
withFileLock(filepath, callback) behavior unchanged and add a brief comment
noting JSON-specific initialization.
- Around line 97-109: The current existsSync -> unlinkSync flow around lockPath
causes a race and never validates the PID; instead, read the lock file contents
(fs.readFileSync(lockPath)) to extract the PID, get lockStat.mtimeMs and compute
age against staleLockAge, then if age > staleLockAge use process.kill(pid, 0)
(or equivalent) to confirm the PID is not alive; before removing, re-read the
file and ensure the PID has not changed and the file still exists, then call
fs.unlinkSync(lockPath) in a try/catch to remove the stale lock; reference
lockPath, staleLockAge, lockStat, mtimeMs, fs.readFileSync, fs.unlinkSync and
process.kill when implementing this check-and-delete-with-verify flow to avoid
deleting a newly created lock.
🧹 Nitpick comments (6)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (2)
6-6: Remove unused import.The
fsSyncimport from 'node:fs' is not used anywhere in the file.♻️ Proposed fix
-import fsSync from 'node:fs';
30-31: Consider removing unused in-memory lock infrastructure.The
fileLocksmap (line 31) andcleanupmethod (lines 198-204) appear to be remnants from the previous in-memory locking implementation. Since the code now uses proper-lockfile for cross-process locking, the in-memory lock map is never populated and the cleanup method is effectively a no-op.♻️ Proposed cleanup
- // In-memory locks are kept as a fallback for cases where file locking fails - private fileLocks: Map<string, Promise<void>> = new Map(); - /** * Read and parse JSON file */- /** - * Clean up all pending file operations - */ - async cleanup(): Promise<void> { - const locks = Array.from(this.fileLocks.values()); - if (locks.length > 0) { - await Promise.all(locks); - } - this.fileLocks.clear(); - }If in-memory locking is intentionally kept as a fallback, please add comments explaining when and how it's used.
Also applies to: 198-204
tests/unit/file-locking.test.js (2)
256-291: Good test coverage for stale lock detection.The test correctly verifies that stale locks don't block new lock acquisition. Consider enhancing the test to verify that the stale lock file is actually removed after being detected.
🧪 Enhancement: Verify stale lock file removal
// Should be able to acquire lock despite existing lock file const result = utils.withFileLockSync(testFilePath, () => 'acquired'); expect(result).toBe('acquired'); + + // Verify the stale lock was removed (may be replaced by new lock during acquisition) + // After lock is released, there should be no lock file + expect(fs.existsSync(lockPath)).toBe(false); });
1-291: Consider adding tests for FileOperations class methods.The current test suite comprehensively tests the utils.js locking utilities (withFileLockSync, writeJSON, readJSON). However, the FileOperations class in packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts also has new methods (exists, getStats, readDir, ensureDir, deleteFile, moveFile, copyFile) that should be tested independently.
Would you like me to generate a test suite for the FileOperations class methods?
scripts/modules/utils.js (2)
63-64: Use getDebugFlag() for consistency instead of direct environment access.Direct access to
process.env.TASKMASTER_DEBUGbypasses the centralized debug configuration. Per coding guidelines, usegetDebugFlag()from config-manager.js for consistency.♻️ Proposed refactor
+ let isDebug = false; + try { + isDebug = getDebugFlag(); + } catch { + // Fallback during config loading + } try { await release(); } catch (releaseError) { // Log but don't throw - lock may have been released already - if (process.env.TASKMASTER_DEBUG === 'true') { + if (isDebug) { console.log(`[DEBUG] Error releasing lock: ${releaseError.message}`); } }
962-976: Temp file cleanup could silently fail and leak files.The error handling for temp file cleanup (lines 968-974) catches and ignores all errors. While this prevents crashes, it could lead to accumulated temp files if cleanup repeatedly fails (e.g., permission issues).
Consider logging cleanup failures at least at debug level, and potentially implementing a separate cleanup mechanism for orphaned temp files.
📝 Proposed improvement
} catch (writeError) { // Clean up temp file on failure try { if (fs.existsSync(tempPath)) { fs.unlinkSync(tempPath); } - } catch { - // Ignore cleanup errors + } catch (cleanupError) { + // Log cleanup failures for debugging + if (isDebug) { + console.log(`[DEBUG] Failed to clean up temp file ${tempPath}: ${cleanupError.message}`); + } } throw writeError; }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (6)
.changeset/fix-file-locking.mdpackage.jsonpackages/tm-core/package.jsonpackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.jstests/unit/file-locking.test.js
🧰 Additional context used
📓 Path-based instructions (15)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.jstests/unit/file-locking.test.js
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Import modules with
.jsextension even in TypeScript source files for ESM compatibility
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
scripts/modules/utils.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
When adding utilities to
utils.js, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Files:
scripts/modules/utils.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
**/*.js: Always use isSilentMode() function to check current silent mode status instead of directly accessing the global silentMode variable or global.silentMode
Use try/finally block pattern when wrapping core function calls with enableSilentMode/disableSilentMode to ensure silent mode is always restored, even if errors occur
For functions that need to handle both a passed silentMode parameter and check global state, check both the function parameter and global state: const isSilent = options.silentMode || (typeof options.silentMode === 'undefined' && isSilentMode())
Functions should accept their dependencies as parameters rather than using globals to promote testability and explicit dependency injection
Define callbacks as separate functions for easier testing rather than inline functions
Files:
scripts/modules/utils.jstests/unit/file-locking.test.js
scripts/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/context_gathering.mdc)
scripts/**/*.js: Use theContextGathererclass fromscripts/modules/utils/contextGatherer.jsto extract context from multiple sources (tasks, files, custom text, project tree) with token counting usinggpt-tokenslibrary
InitializeContextGathererwith project root and tasks path, then callgather()method with tasks array, files array, customContext, includeProjectTree, format ('research', 'chat', or 'system-prompt'), and includeTokenCounts options
Use theFuzzyTaskSearchclass fromscripts/modules/utils/fuzzyTaskSearch.jsfor intelligent task discovery with semantic matching, purpose categorization, and relevance scoring using Fuse.js
Implement a three-step initialization pattern for context-aware commands: (1) validate and parse parameters, (2) initialize context gatherer and find project root, (3) auto-discover relevant tasks using fuzzy search if task IDs not specified
Display token breakdown usingboxenlibrary with sections for tasks, files, and prompts, showing formatted token counts and file sizes in a clean bordered box with title
Process AI result responses usingcli-highlightlibrary to apply syntax highlighting to code blocks with language detection in the formatlanguage\ncode
Set reasonable file size limits (50KB default) and project tree depth limits (3-5 levels) when gathering context to maintain performance
Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior
Files:
scripts/modules/utils.js
scripts/modules/**/*
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
Restart the MCP server if core logic in
scripts/modulesor MCP tool definitions change
Files:
scripts/modules/utils.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/mcp.mdc)
When implementing MCP support for a command, ensure the core logic function can suppress console output via an outputFormat parameter or other mechanism
scripts/modules/*.js: Use consistent file naming conventions:task_${id.toString().padStart(3, '0')}.txtfor task files; usepath.join()for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
UseisSilentMode()function to check global silent mode status; wrap core function calls within direct functions usingenableSilentMode()anddisableSilentMode()in try/finally blocks if the core function produces console output not reliably controlled by outputFormat parameter
Ensure AI calls correctly handle and propagatetelemetryDataas described intelemetry.mdc
Import context gathering utilities (ContextGatherer,FuzzyTaskSearch) for AI-powered commands; support multiple context types (tasks, files, custom text, project tree); implement detailed token breakdown display
PrefergenerateTextServicefor calls sending large context (like stringified JSON) where incremental display is not needed; import necessary service functions fromai-services-unified.jsand prepare parameters (role, session, systemPrompt, prompt)
Create a clear unidirectional flow of dependencies between modules; separate business logic from UI rendering to avoid circular dependencies
Design functions to accept dependencies as parameters; avoid hard-coded dependencies that are difficult to mock
Keep pure logic separate from I/O operations or UI rendering to allow testing logic without mocking complex dependencies
Design core logic to work wi...
Files:
scripts/modules/utils.js
**/*.{js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
JavaScript test files using Jest must follow the same testing patterns as TypeScript files, include proper mocking of external dependencies, and achieve the same coverage thresholds
Files:
scripts/modules/utils.jstests/unit/file-locking.test.js
scripts/modules/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
scripts/modules/**/*.{js,ts}: Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
When a logger object is passed as a parameter to core functions, ensure the receiving function can call methods like .info, .warn, .error on that object
Files:
scripts/modules/utils.js
tests/unit/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
Unit tests should be located in tests/unit/ and reflect the module structure with one test file per module
Files:
tests/unit/file-locking.test.js
**/*.test.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/new_features.mdc)
**/*.test.{js,ts}: Follow the mock-first-then-import pattern for Jest mocking; use jest.spyOn() for spy functions; clear mocks between tests; verify mocks with the pattern described intests.mdc
Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Files:
tests/unit/file-locking.test.js
**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
**/*.test.js: Never use asynchronous operations in tests. Always mock tests properly based on the way the tested functions are defined and used.
Follow Jest test file structure: 1) Imports, 2) Mock setup before importing modules under test, 3) Import modules after mocks, 4) Set up spies on mocked modules, 5) Describe suite with descriptive name, 6) Setup/teardown hooks, 7) Grouped tests for related functionality, 8) Individual test cases with clear descriptions using Arrange-Act-Assert pattern.
When testing CLI commands built with Commander.js: test command action handlers directly rather than mocking the entire Commander chain; create simplified test-specific implementations of command handlers; explicitly handle all options including defaults and shorthand flags; include null/undefined checks for optional parameters; use fixtures for consistent sample data.
Usejest.mock()before any imports. Jest hoists mock calls to the top of the file. Always declare mocks before importing modules being tested. Use factory pattern for complex mocks that need access to other variables.
When testing ES modules with dynamic imports, usejest.unstable_mockModule()beforeawait import(). Include__esModule: truein mock factories. Reset mock functions before dynamic import. Mock named and default exports as needed.
Mock file system operations usingmock-fslibrary. Mock API calls by providing jest.fn() implementations that return expected structures. Mock environment variables in test setup.
When testing functions with callbacks: get the callback from mock's call arguments usingmock.calls[index][argIndex]; execute it directly with test inputs; verify results match expectations.
For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mockreadJSONandwriteJSONto avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed t...
Files:
tests/unit/file-locking.test.js
tests/unit/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
Locate unit tests in
tests/unit/directory. Test individual functions and utilities in isolation, mock all external dependencies, keep tests small and focused.
Files:
tests/unit/file-locking.test.js
package.json
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
package.json scripts must include: 'test', 'test:watch', 'test:coverage', 'test:unit', 'test:integration', 'test:e2e', and 'test:ci' commands for testing framework integration
Files:
package.json
🧠 Learnings (61)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/**/CLAUDE.md : Update `CLAUDE.md` file with project-specific context, task summaries, and custom command examples for Claude Code integration
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/.claude/settings.json : Add Claude Code tool allowlist configuration in `.claude/settings.json` to include 'Edit', 'Bash(task-master *)', 'Bash(git commit:*)', 'Bash(git add:*)', 'Bash(npm run *)', and 'mcp__task_master_ai__*'
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1194
File: .github/workflows/ci.yml:31-35
Timestamp: 2025-09-09T19:13:55.652Z
Learning: The claude-task-master project has only one package-lock.json file in the entire workspace (at the root level), so cache-dependency-path configuration is unnecessary for the npm cache in GitHub Actions.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Use git worktrees for parallel Task Master task development with separate Claude Code sessions in each worktree
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 943
File: scripts/modules/task-manager/move-task.js:24-24
Timestamp: 2025-07-18T05:38:17.352Z
Learning: In the Claude Task Master system, core task-manager functions are designed with fallback mechanisms for missing projectRoot parameters using the pattern `const projectRoot = providedProjectRoot || findProjectRoot();`. The readJSON and writeJSON functions have default parameters (projectRoot = null, tag = null) and handle missing parameters gracefully. Adding strict validation to these core functions would break the established flexible architecture pattern.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/auth/oauth-service.ts:20-20
Timestamp: 2025-09-03T13:46:00.640Z
Learning: For Node.js v22 and later, JSON imports should use `with { type: 'json' }` syntax, not `assert { type: 'json' }`. The `assert` syntax was removed in Node.js v22 in favor of the `with` syntax for import attributes. This applies to the eyaltoledano/claude-task-master codebase which uses Node.js v24.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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.
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.jstests/unit/file-locking.test.js.changeset/fix-file-locking.md
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tspackage.json
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to packages/tm-core/**/*.{spec,test}.ts : In unit tests for tm/core, mock only external I/O (Supabase, APIs, filesystem) and use real internal services
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.jstests/unit/file-locking.test.js.changeset/fix-file-locking.md
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use path.join() instead of string concatenation for file paths, follow established file naming conventions (task_001.txt format), and use path.dirname() and related path utilities for manipulating paths
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-09-26T19:03:33.225Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1252
File: package.json:130-132
Timestamp: 2025-09-26T19:03:33.225Z
Learning: In the eyaltoledano/claude-task-master repository, packages are bundled using tsdown during the build process, which means dependencies imported by the source code (including tm internal packages like tm/ai-sdk-provider-grok-cli) are included in the final bundle and don't need to be available as separate runtime dependencies, so they should remain as devDependencies rather than being moved to dependencies.
Applied to files:
packages/tm-core/package.jsonpackage.json
📚 Learning: 2025-09-26T19:07:10.485Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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:
packages/tm-core/package.jsonpackage.json
📚 Learning: 2025-09-26T19:05:47.555Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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/package.jsonpackage.json
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Track and report changes made during dependency cleanup
Applied to files:
packages/tm-core/package.jsonscripts/modules/utils.jspackage.json
📚 Learning: 2025-09-22T19:45:04.337Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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:
packages/tm-core/package.jsonpackage.json
📚 Learning: 2025-10-08T19:57:00.982Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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/package.json
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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/package.jsonpackage.json.changeset/fix-file-locking.md
📚 Learning: 2025-09-03T12:16:15.866Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/package.json:13-64
Timestamp: 2025-09-03T12:16:15.866Z
Learning: For internal packages in the claude-task-master project, Crunchyman-ralph prefers pointing package.json "types" entries to src .ts files rather than dist .d.ts files for better developer experience (DX), as the packages are not being exported as SDKs.
Applied to files:
packages/tm-core/package.json
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Applies to package.json : package.json scripts must include: 'test', 'test:watch', 'test:coverage', 'test:unit', 'test:integration', 'test:e2e', and 'test:ci' commands for testing framework integration
Applied to files:
packages/tm-core/package.jsonpackage.json
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Place utilities used primarily by the core task-master CLI logic and command modules into scripts/modules/utils.js
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Organize imports by module/functionality, import only what's needed (not entire modules), and avoid creating circular dependencies
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys with helpful hints for fallbacks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Wrap async operations in try/catch blocks, display user-friendly error messages, and include detailed error information in debug mode
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/commands/**/*.{js,ts} : Handle potential ConfigurationError if the .taskmasterconfig file is missing or invalid when accessed via getConfig
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Pass context object `{ projectRoot, tag }` to all core functions that read or write tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T05:38:17.352Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 943
File: scripts/modules/task-manager/move-task.js:24-24
Timestamp: 2025-07-18T05:38:17.352Z
Learning: In the Claude Task Master system, core task-manager functions are designed with fallback mechanisms for missing projectRoot parameters using the pattern `const projectRoot = providedProjectRoot || findProjectRoot();`. The readJSON and writeJSON functions have default parameters (projectRoot = null, tag = null) and handle missing parameters gracefully. Adding strict validation to these core functions would break the established flexible architecture pattern.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Core task functions must accept a context parameter with `{ projectRoot, tag }` properties
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Design core logic to work with both legacy (flat tasks array) and tagged task data formats; use tag resolution functions (getTasksForTag, setTasksForTag) for task data access; support silent migration during feature usage
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Applied to files:
scripts/modules/utils.js.changeset/fix-file-locking.md
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Implement silent migration in readJSON() function to automatically convert legacy tasks.json format ({"tasks": [...]}) to tagged format ({"master": {"tasks": [...]}}) on first use while preserving all existing task data
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Implement reusable task finding utilities that support both task and subtask lookups and add context to subtask results
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent properties for subtasks (id, title, description, status, dependencies, details) without duplicating parent task properties, maintaining simple numeric IDs unique within the parent task
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Include all required task properties (id, title, description, status, dependencies, priority, details, testStrategy, subtasks) in each task object without adding extra properties outside the standard schema
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to tests/unit/**/*.test.js : Locate unit tests in `tests/unit/` directory. Test individual functions and utilities in isolation, mock all external dependencies, keep tests small and focused.
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Create simplified test functions instead of complex setups: create simplified versions of complex functions focusing on core logic; remove file system operations, API calls, and external dependencies; pass all dependencies as parameters.
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Follow Jest test file structure: 1) Imports, 2) Mock setup before importing modules under test, 3) Import modules after mocks, 4) Set up spies on mocked modules, 5) Describe suite with descriptive name, 6) Setup/teardown hooks, 7) Grouped tests for related functionality, 8) Individual test cases with clear descriptions using Arrange-Act-Assert pattern.
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to tests/integration/**/*.test.js : Locate integration tests in `tests/integration/` directory. Test interactions between modules, focus on component interfaces rather than implementation details, use more realistic but controlled test environments.
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Applies to tests/teardown.ts : Global teardown file must be created to handle cleanup after all tests complete and prevent worker process leaks
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Mock file system operations using `mock-fs` library. Mock API calls by providing jest.fn() implementations that return expected structures. Mock environment variables in test setup.
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : When testing CLI commands built with Commander.js: test command action handlers directly rather than mocking the entire Commander chain; create simplified test-specific implementations of command handlers; explicitly handle all options including defaults and shorthand flags; include null/undefined checks for optional parameters; use fixtures for consistent sample data.
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Test files must be organized with unit tests separate from integration and e2e tests using project configuration in jest.config.js to maintain clear test separation and different timeout/environment settings
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Never use asynchronous operations in tests. Always mock tests properly based on the way the tested functions are defined and used.
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-08-07T13:00:22.966Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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:
package.json
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Format task and dependency IDs consistently, check for existing dependencies to prevent duplicates, and sort dependencies for better readability when adding dependencies
Applied to files:
package.json
📚 Learning: 2025-09-09T19:13:55.652Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1194
File: .github/workflows/ci.yml:31-35
Timestamp: 2025-09-09T19:13:55.652Z
Learning: The claude-task-master project has only one package-lock.json file in the entire workspace (at the root level), so cache-dependency-path configuration is unnecessary for the npm cache in GitHub Actions.
Applied to files:
package.json.changeset/fix-file-locking.md
📚 Learning: 2025-09-17T20:26:17.277Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1213
File: .github/workflows/pre-release.yml:68-73
Timestamp: 2025-09-17T20:26:17.277Z
Learning: User Crunchyman-ralph clarified that not all packages in the monorepo need build steps, so adding turbo:build scripts to every workspace package.json is unnecessary and incorrect.
Applied to files:
package.json
📚 Learning: 2025-11-24T17:57:14.743Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-11-24T17:57:14.743Z
Learning: Applies to src/ai-providers/*.js : Provider modules in `src/ai-providers/` must import `generateText`, `streamText`, `generateObject` from the `ai` package, the provider's `create<ProviderName>` function from `ai-sdk/<provider-name>`, and the `log` utility from `../../scripts/modules/utils.js`
Applied to files:
package.json
📚 Learning: 2025-12-11T14:45:14.973Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/**/CLAUDE.md : Update `CLAUDE.md` file with project-specific context, task summaries, and custom command examples for Claude Code integration
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-09-03T13:46:00.640Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/auth/oauth-service.ts:20-20
Timestamp: 2025-09-03T13:46:00.640Z
Learning: For Node.js v22 and later, JSON imports should use `with { type: 'json' }` syntax, not `assert { type: 'json' }`. The `assert` syntax was removed in Node.js v22 in favor of the `with` syntax for import attributes. This applies to the eyaltoledano/claude-task-master codebase which uses Node.js v24.
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-12-11T14:45:14.973Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/.claude/settings.json : Add Claude Code tool allowlist configuration in `.claude/settings.json` to include 'Edit', 'Bash(task-master *)', 'Bash(git commit:*)', 'Bash(git add:*)', 'Bash(npm run *)', and 'mcp__task_master_ai__*'
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-11-25T18:32:29.828Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to mcp-server/src/core/task-master-core.js : Update `task-master-core.js` by importing and re-exporting direct functions and adding them to the directFunctions map
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-12-11T14:45:14.973Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Use git worktrees for parallel Task Master task development with separate Claude Code sessions in each worktree
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-09-22T19:45:13.323Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1232
File: packages/build-config/package.json:14-15
Timestamp: 2025-09-22T19:45:13.323Z
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:
.changeset/fix-file-locking.md
🧬 Code graph analysis (2)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (1)
scripts/modules/utils.js (1)
LOCK_OPTIONS(24-33)
tests/unit/file-locking.test.js (2)
scripts/modules/utils.js (3)
result(634-638)data(461-461)lockPath(88-88)tests/unit/task-manager/tag-management.test.js (1)
initialData(18-26)
🪛 LanguageTool
.changeset/fix-file-locking.md
[grammar] ~11-~11: Use a hyphen to join words.
Context: ...lock detection and automatic cleanup (10 second timeout) - Export withFileLock ...
(QB_NEW_EN_HYPHEN)
⏰ 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). (2)
- GitHub Check: Build
- GitHub Check: Cursor Bugbot
There was a problem hiding this comment.
This is the final PR Bugbot will review for you during this billing cycle
Your free Bugbot reviews will reset on January 9
Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In
@packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts:
- Around line 80-89: The current ensureFileExists causes a TOCTOU race because
it creates the file before the lock is taken; move the creation logic inside the
critical section (i.e., after the lock is acquired) or perform atomic creation
using exclusive flags: ensure the directory exists (fs.mkdir with recursive) and
then attempt an exclusive create (fs.writeFile or fs.open with flag 'wx'), catch
EEXIST and ignore it, and after successful or ignored creation proceed to
read/write; update the ensureFileExists function (and any call sites where the
lock is acquired) to reflect this change so two processes cannot both
create/overwrite the file concurrently.
In @scripts/modules/utils.js:
- Around line 946-957: The cleanup logic currently destructures away created and
description from each tag object (const { created, description, ...cleanTagData
} = value) but only conditionally restores description, causing the created
timestamp to be lost; update the code that builds cleanTagData so it preserves
created as well (e.g., ensure created is copied back into cleanTagData when
present) while still applying the existing rule to only add description if
metadata.description is missing, and then assign the resulting object to
finalCleanData[key].
🧹 Nitpick comments (1)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (1)
29-30: UnusedfileLocksmap is dead code.The
fileLocksmap is declared as a "fallback" but is never populated duringwriteJsonoperations. Thecleanup()method at lines 197-203 will always operate on an empty map. Either implement the fallback logic or remove this dead code.♻️ Proposed removal
export class FileOperations { - // In-memory locks are kept as a fallback for cases where file locking fails - private fileLocks: Map<string, Promise<void>> = new Map(); // ... other methods ... - /** - * Clean up all pending file operations - */ - async cleanup(): Promise<void> { - const locks = Array.from(this.fileLocks.values()); - if (locks.length > 0) { - await Promise.all(locks); - } - this.fileLocks.clear(); - } + /** + * Clean up all pending file operations (no-op, reserved for future use) + */ + async cleanup(): Promise<void> { + // No pending operations to clean up with cross-process locking + } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
package.jsonpackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.jstests/unit/file-locking.test.js
🚧 Files skipped from review as they are similar to previous changes (2)
- package.json
- tests/unit/file-locking.test.js
🧰 Additional context used
📓 Path-based instructions (10)
scripts/modules/utils.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
When adding utilities to
utils.js, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Files:
scripts/modules/utils.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
**/*.js: Always use isSilentMode() function to check current silent mode status instead of directly accessing the global silentMode variable or global.silentMode
Use try/finally block pattern when wrapping core function calls with enableSilentMode/disableSilentMode to ensure silent mode is always restored, even if errors occur
For functions that need to handle both a passed silentMode parameter and check global state, check both the function parameter and global state: const isSilent = options.silentMode || (typeof options.silentMode === 'undefined' && isSilentMode())
Functions should accept their dependencies as parameters rather than using globals to promote testability and explicit dependency injection
Define callbacks as separate functions for easier testing rather than inline functions
Files:
scripts/modules/utils.js
scripts/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/context_gathering.mdc)
scripts/**/*.js: Use theContextGathererclass fromscripts/modules/utils/contextGatherer.jsto extract context from multiple sources (tasks, files, custom text, project tree) with token counting usinggpt-tokenslibrary
InitializeContextGathererwith project root and tasks path, then callgather()method with tasks array, files array, customContext, includeProjectTree, format ('research', 'chat', or 'system-prompt'), and includeTokenCounts options
Use theFuzzyTaskSearchclass fromscripts/modules/utils/fuzzyTaskSearch.jsfor intelligent task discovery with semantic matching, purpose categorization, and relevance scoring using Fuse.js
Implement a three-step initialization pattern for context-aware commands: (1) validate and parse parameters, (2) initialize context gatherer and find project root, (3) auto-discover relevant tasks using fuzzy search if task IDs not specified
Display token breakdown usingboxenlibrary with sections for tasks, files, and prompts, showing formatted token counts and file sizes in a clean bordered box with title
Process AI result responses usingcli-highlightlibrary to apply syntax highlighting to code blocks with language detection in the formatlanguage\ncode
Set reasonable file size limits (50KB default) and project tree depth limits (3-5 levels) when gathering context to maintain performance
Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior
Files:
scripts/modules/utils.js
scripts/modules/**/*
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
Restart the MCP server if core logic in
scripts/modulesor MCP tool definitions change
Files:
scripts/modules/utils.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/mcp.mdc)
When implementing MCP support for a command, ensure the core logic function can suppress console output via an outputFormat parameter or other mechanism
scripts/modules/*.js: Use consistent file naming conventions:task_${id.toString().padStart(3, '0')}.txtfor task files; usepath.join()for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
UseisSilentMode()function to check global silent mode status; wrap core function calls within direct functions usingenableSilentMode()anddisableSilentMode()in try/finally blocks if the core function produces console output not reliably controlled by outputFormat parameter
Ensure AI calls correctly handle and propagatetelemetryDataas described intelemetry.mdc
Import context gathering utilities (ContextGatherer,FuzzyTaskSearch) for AI-powered commands; support multiple context types (tasks, files, custom text, project tree); implement detailed token breakdown display
PrefergenerateTextServicefor calls sending large context (like stringified JSON) where incremental display is not needed; import necessary service functions fromai-services-unified.jsand prepare parameters (role, session, systemPrompt, prompt)
Create a clear unidirectional flow of dependencies between modules; separate business logic from UI rendering to avoid circular dependencies
Design functions to accept dependencies as parameters; avoid hard-coded dependencies that are difficult to mock
Keep pure logic separate from I/O operations or UI rendering to allow testing logic without mocking complex dependencies
Design core logic to work wi...
Files:
scripts/modules/utils.js
**/*.{js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
JavaScript test files using Jest must follow the same testing patterns as TypeScript files, include proper mocking of external dependencies, and achieve the same coverage thresholds
Files:
scripts/modules/utils.js
**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements
Files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
scripts/modules/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
scripts/modules/**/*.{js,ts}: Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
When a logger object is passed as a parameter to core functions, ensure the receiving function can call methods like .info, .warn, .error on that object
Files:
scripts/modules/utils.js
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Import modules with
.jsextension even in TypeScript source files for ESM compatibility
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧠 Learnings (43)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/**/CLAUDE.md : Update `CLAUDE.md` file with project-specific context, task summaries, and custom command examples for Claude Code integration
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use findTasksJsonPath utility within direct functions to locate the tasks.json file consistently
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Create utilities for consistent task ID handling that support different ID formats (numeric, string, dot notation)
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Place utilities used primarily by the core task-master CLI logic and command modules into scripts/modules/utils.js
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/utils.js : When adding utilities to `utils.js`, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Group related exports together in utility modules and avoid creating circular dependencies
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Export all utility functions explicitly in logical groups and include configuration constants from utility modules
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys with helpful hints for fallbacks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys for features that depend on them.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/init.js : init.js should create necessary directories and files for new projects, set up tasks.json with tagged structure, configure project metadata, initialize state.json for tag system, handle shell alias creation, and support both interactive and non-interactive modes
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T05:38:17.352Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 943
File: scripts/modules/task-manager/move-task.js:24-24
Timestamp: 2025-07-18T05:38:17.352Z
Learning: In the Claude Task Master system, core task-manager functions are designed with fallback mechanisms for missing projectRoot parameters using the pattern `const projectRoot = providedProjectRoot || findProjectRoot();`. The readJSON and writeJSON functions have default parameters (projectRoot = null, tag = null) and handle missing parameters gracefully. Adding strict validation to these core functions would break the established flexible architecture pattern.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : For file path handling in destructive operations: use path.join() to construct paths, follow naming conventions (e.g., task_001.txt), check file existence before deletion, and handle errors gracefully without string concatenation
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use consistent file naming conventions: `task_${id.toString().padStart(3, '0')}.txt` for task files; use `path.join()` for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Design core logic to work with both legacy (flat tasks array) and tagged task data formats; use tag resolution functions (getTasksForTag, setTasksForTag) for task data access; support silent migration during feature usage
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : In MCP direct functions, support explicit tag specification and use tag resolution for task data operations; default to current tag when not specified
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-08-06T21:12:43.715Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-orchestrator.md:1-6
Timestamp: 2025-08-06T21:12:43.715Z
Learning: In the eyaltoledano/claude-task-master repository, agent files are intentionally duplicated between `.claude/agents/` (for internal project use) and `assets/claude/agents/` (as template files for users to copy). This duplication serves different purposes and should be maintained to support both internal development and user distribution needs.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-08-06T21:12:20.981Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-executor.md:1-6
Timestamp: 2025-08-06T21:12:20.981Z
Learning: In the eyaltoledano/claude-task-master repository, agent files in assets/claude/agents/ are intended for distribution to users (for copying), while identical files in .claude/agents/ are for internal project use. This intentional duplication serves different purposes and is not a DRY violation.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/task-manager.js : Data manipulation features (create, read, update, delete tasks) should be placed in `task-manager.js` and follow guidelines in `tasks.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/commands/**/*.{js,ts} : Handle potential ConfigurationError if the .taskmasterconfig file is missing or invalid when accessed via getConfig
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use path.join() instead of string concatenation for file paths, follow established file naming conventions (task_001.txt format), and use path.dirname() and related path utilities for manipulating paths
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Pass context object `{ projectRoot, tag }` to all core functions that read or write tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Core task functions must accept a context parameter with `{ projectRoot, tag }` properties
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Implement silent migration in readJSON() function to automatically convert legacy tasks.json format ({"tasks": [...]}) to tagged format ({"master": {"tasks": [...]}}) on first use while preserving all existing task data
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Implement reusable task finding utilities that support both task and subtask lookups and add context to subtask results
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent properties for subtasks (id, title, description, status, dependencies, details) without duplicating parent task properties, maintaining simple numeric IDs unique within the parent task
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Include all required task properties (id, title, description, status, dependencies, priority, details, testStrategy, subtasks) in each task object without adding extra properties outside the standard schema
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to packages/tm-core/**/*.{spec,test}.ts : In unit tests for tm/core, mock only external I/O (Supabase, APIs, filesystem) and use real internal services
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Log detailed error information using the log utility in catch blocks for file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧬 Code graph analysis (2)
scripts/modules/utils.js (3)
scripts/modules/task-manager/update-task-by-id.js (2)
data(120-120)projectRoot(77-77)scripts/modules/ui.js (5)
data(986-986)data(1266-1266)data(2380-2380)projectRoot(2376-2376)tag(2377-2377)mcp-server/src/core/direct-functions/expand-task.js (1)
data(103-103)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (1)
scripts/modules/utils.js (1)
LOCK_OPTIONS(24-33)
⏰ 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: Cursor Bugbot
🔇 Additional comments (3)
scripts/modules/utils.js (1)
1796-1798: LGTM!The new locking utilities are correctly exported, enabling cross-process file safety for consumers of this module. As per coding guidelines, these utilities can be used by multiple modules and are appropriately placed in utils.js.
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (2)
14-23: LGTM!The
LOCK_OPTIONSconfiguration is consistent withscripts/modules/utils.js, ensuring uniform locking behavior across the codebase.
94-114: LGTM!The atomic write implementation correctly uses a PID-suffixed temp file to prevent collisions between processes, with proper cleanup on error. The rename operation provides atomicity guarantees on POSIX systems.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In
@packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts:
- Around line 123-135: In ensureFileExists change the non-atomic create to an
exclusive write: after ensuring the directory exists (keep fs.mkdir(dir, {
recursive: true })), call fs.writeFile(filePath, '{}', { encoding: 'utf8', flag:
'wx' }) and catch errors; if the error.code is 'EEXIST' simply ignore it
(another process created the file) and rethrow other errors. This makes creation
atomic and avoids the TOCTOU race in the ensureFileExists method.
In @scripts/modules/utils.js:
- Around line 42-51: The withFileLock function currently checks and creates the
target file before acquiring the lock, allowing a race where two processes both
write '{}' and overwrite each other; change the creation step to attempt
exclusive creation using fs.writeFileSync(filepath, '{}', { flag: 'wx',
encoding: 'utf8' }) (or fs.openSync with 'wx') so the call fails with EEXIST if
another process created the file concurrently, catch EEXIST and proceed without
overwriting, ensure the directory creation (path.dirname(filepath)) remains
before this attempt, and keep the lock acquisition and callback logic intact in
the existing withFileLock flow.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.changeset/fix-file-locking.mdpackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.js
🧰 Additional context used
📓 Path-based instructions (10)
scripts/modules/utils.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
When adding utilities to
utils.js, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Files:
scripts/modules/utils.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
**/*.js: Always use isSilentMode() function to check current silent mode status instead of directly accessing the global silentMode variable or global.silentMode
Use try/finally block pattern when wrapping core function calls with enableSilentMode/disableSilentMode to ensure silent mode is always restored, even if errors occur
For functions that need to handle both a passed silentMode parameter and check global state, check both the function parameter and global state: const isSilent = options.silentMode || (typeof options.silentMode === 'undefined' && isSilentMode())
Functions should accept their dependencies as parameters rather than using globals to promote testability and explicit dependency injection
Define callbacks as separate functions for easier testing rather than inline functions
Files:
scripts/modules/utils.js
scripts/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/context_gathering.mdc)
scripts/**/*.js: Use theContextGathererclass fromscripts/modules/utils/contextGatherer.jsto extract context from multiple sources (tasks, files, custom text, project tree) with token counting usinggpt-tokenslibrary
InitializeContextGathererwith project root and tasks path, then callgather()method with tasks array, files array, customContext, includeProjectTree, format ('research', 'chat', or 'system-prompt'), and includeTokenCounts options
Use theFuzzyTaskSearchclass fromscripts/modules/utils/fuzzyTaskSearch.jsfor intelligent task discovery with semantic matching, purpose categorization, and relevance scoring using Fuse.js
Implement a three-step initialization pattern for context-aware commands: (1) validate and parse parameters, (2) initialize context gatherer and find project root, (3) auto-discover relevant tasks using fuzzy search if task IDs not specified
Display token breakdown usingboxenlibrary with sections for tasks, files, and prompts, showing formatted token counts and file sizes in a clean bordered box with title
Process AI result responses usingcli-highlightlibrary to apply syntax highlighting to code blocks with language detection in the formatlanguage\ncode
Set reasonable file size limits (50KB default) and project tree depth limits (3-5 levels) when gathering context to maintain performance
Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior
Files:
scripts/modules/utils.js
scripts/modules/**/*
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
Restart the MCP server if core logic in
scripts/modulesor MCP tool definitions change
Files:
scripts/modules/utils.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/mcp.mdc)
When implementing MCP support for a command, ensure the core logic function can suppress console output via an outputFormat parameter or other mechanism
scripts/modules/*.js: Use consistent file naming conventions:task_${id.toString().padStart(3, '0')}.txtfor task files; usepath.join()for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
UseisSilentMode()function to check global silent mode status; wrap core function calls within direct functions usingenableSilentMode()anddisableSilentMode()in try/finally blocks if the core function produces console output not reliably controlled by outputFormat parameter
Ensure AI calls correctly handle and propagatetelemetryDataas described intelemetry.mdc
Import context gathering utilities (ContextGatherer,FuzzyTaskSearch) for AI-powered commands; support multiple context types (tasks, files, custom text, project tree); implement detailed token breakdown display
PrefergenerateTextServicefor calls sending large context (like stringified JSON) where incremental display is not needed; import necessary service functions fromai-services-unified.jsand prepare parameters (role, session, systemPrompt, prompt)
Create a clear unidirectional flow of dependencies between modules; separate business logic from UI rendering to avoid circular dependencies
Design functions to accept dependencies as parameters; avoid hard-coded dependencies that are difficult to mock
Keep pure logic separate from I/O operations or UI rendering to allow testing logic without mocking complex dependencies
Design core logic to work wi...
Files:
scripts/modules/utils.js
**/*.{js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
JavaScript test files using Jest must follow the same testing patterns as TypeScript files, include proper mocking of external dependencies, and achieve the same coverage thresholds
Files:
scripts/modules/utils.js
**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements
Files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
scripts/modules/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
scripts/modules/**/*.{js,ts}: Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
When a logger object is passed as a parameter to core functions, ensure the receiving function can call methods like .info, .warn, .error on that object
Files:
scripts/modules/utils.js
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Import modules with
.jsextension even in TypeScript source files for ESM compatibility
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧠 Learnings (57)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/**/CLAUDE.md : Update `CLAUDE.md` file with project-specific context, task summaries, and custom command examples for Claude Code integration
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1194
File: .github/workflows/ci.yml:31-35
Timestamp: 2025-09-09T19:13:55.652Z
Learning: The claude-task-master project has only one package-lock.json file in the entire workspace (at the root level), so cache-dependency-path configuration is unnecessary for the npm cache in GitHub Actions.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/.claude/settings.json : Add Claude Code tool allowlist configuration in `.claude/settings.json` to include 'Edit', 'Bash(task-master *)', 'Bash(git commit:*)', 'Bash(git add:*)', 'Bash(npm run *)', and 'mcp__task_master_ai__*'
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Create utilities for consistent task ID handling that support different ID formats (numeric, string, dot notation)
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use findTasksJsonPath utility within direct functions to locate the tasks.json file consistently
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/context_gathering.mdc:0-0
Timestamp: 2025-11-24T17:59:00.056Z
Learning: Applies to scripts/**/*.js : Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Applied to files:
.changeset/fix-file-locking.mdscripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Applied to files:
.changeset/fix-file-locking.mdscripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to mcp-server/src/core/task-master-core.js : Update `task-master-core.js` by importing and re-exporting direct functions and adding them to the directFunctions map
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Applied to files:
.changeset/fix-file-locking.mdscripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-09-09T19:13:55.652Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1194
File: .github/workflows/ci.yml:31-35
Timestamp: 2025-09-09T19:13:55.652Z
Learning: The claude-task-master project has only one package-lock.json file in the entire workspace (at the root level), so cache-dependency-path configuration is unnecessary for the npm cache in GitHub Actions.
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-12-11T14:45:14.973Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Use git worktrees for parallel Task Master task development with separate Claude Code sessions in each worktree
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-12-11T14:45:14.973Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/.claude/settings.json : Add Claude Code tool allowlist configuration in `.claude/settings.json` to include 'Edit', 'Bash(task-master *)', 'Bash(git commit:*)', 'Bash(git add:*)', 'Bash(npm run *)', and 'mcp__task_master_ai__*'
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-12-11T14:45:14.973Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/.taskmaster/tasks/tasks.json : Store main task data in `.taskmaster/tasks/tasks.json` and never manually edit this file - use Task Master commands instead
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-09-03T13:46:00.640Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/auth/oauth-service.ts:20-20
Timestamp: 2025-09-03T13:46:00.640Z
Learning: For Node.js v22 and later, JSON imports should use `with { type: 'json' }` syntax, not `assert { type: 'json' }`. The `assert` syntax was removed in Node.js v22 in favor of the `with` syntax for import attributes. This applies to the eyaltoledano/claude-task-master codebase which uses Node.js v24.
Applied to files:
.changeset/fix-file-locking.md
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Place utilities used primarily by the core task-master CLI logic and command modules into scripts/modules/utils.js
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Group related exports together in utility modules and avoid creating circular dependencies
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Export all utility functions explicitly in logical groups and include configuration constants from utility modules
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/utils.js : When adding utilities to `utils.js`, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Log detailed error information using the log utility in catch blocks for file operations
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys with helpful hints for fallbacks
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys for features that depend on them.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/init.js : init.js should create necessary directories and files for new projects, set up tasks.json with tagged structure, configure project metadata, initialize state.json for tag system, handle shell alias creation, and support both interactive and non-interactive modes
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T05:38:17.352Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 943
File: scripts/modules/task-manager/move-task.js:24-24
Timestamp: 2025-07-18T05:38:17.352Z
Learning: In the Claude Task Master system, core task-manager functions are designed with fallback mechanisms for missing projectRoot parameters using the pattern `const projectRoot = providedProjectRoot || findProjectRoot();`. The readJSON and writeJSON functions have default parameters (projectRoot = null, tag = null) and handle missing parameters gracefully. Adding strict validation to these core functions would break the established flexible architecture pattern.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : For file path handling in destructive operations: use path.join() to construct paths, follow naming conventions (e.g., task_001.txt), check file existence before deletion, and handle errors gracefully without string concatenation
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use consistent file naming conventions: `task_${id.toString().padStart(3, '0')}.txt` for task files; use `path.join()` for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Design core logic to work with both legacy (flat tasks array) and tagged task data formats; use tag resolution functions (getTasksForTag, setTasksForTag) for task data access; support silent migration during feature usage
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : In MCP direct functions, support explicit tag specification and use tag resolution for task data operations; default to current tag when not specified
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-08-06T21:12:43.715Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-orchestrator.md:1-6
Timestamp: 2025-08-06T21:12:43.715Z
Learning: In the eyaltoledano/claude-task-master repository, agent files are intentionally duplicated between `.claude/agents/` (for internal project use) and `assets/claude/agents/` (as template files for users to copy). This duplication serves different purposes and should be maintained to support both internal development and user distribution needs.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-08-06T21:12:20.981Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-executor.md:1-6
Timestamp: 2025-08-06T21:12:20.981Z
Learning: In the eyaltoledano/claude-task-master repository, agent files in assets/claude/agents/ are intended for distribution to users (for copying), while identical files in .claude/agents/ are for internal project use. This intentional duplication serves different purposes and is not a DRY violation.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/task-manager.js : Data manipulation features (create, read, update, delete tasks) should be placed in `task-manager.js` and follow guidelines in `tasks.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/commands/**/*.{js,ts} : Handle potential ConfigurationError if the .taskmasterconfig file is missing or invalid when accessed via getConfig
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use path.join() instead of string concatenation for file paths, follow established file naming conventions (task_001.txt format), and use path.dirname() and related path utilities for manipulating paths
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks and self-references during cleanup, tracking and reporting changes made during cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI within the current tag context (defaulting to "master"), providing clear prompts to guide AI task generation and validating/cleaning up AI-generated tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data after destructive operations, handling both direct and indirect references with explanatory console logging
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data, handle both direct and indirect references, and explain what related data is being updated.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks during cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Track and report changes made during dependency cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Pass context object `{ projectRoot, tag }` to all core functions that read or write tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Core task functions must accept a context parameter with `{ projectRoot, tag }` properties
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Implement silent migration in readJSON() function to automatically convert legacy tasks.json format ({"tasks": [...]}) to tagged format ({"master": {"tasks": [...]}}) on first use while preserving all existing task data
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Implement reusable task finding utilities that support both task and subtask lookups and add context to subtask results
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent properties for subtasks (id, title, description, status, dependencies, details) without duplicating parent task properties, maintaining simple numeric IDs unique within the parent task
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Include all required task properties (id, title, description, status, dependencies, priority, details, testStrategy, subtasks) in each task object without adding extra properties outside the standard schema
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to packages/tm-core/**/*.{spec,test}.ts : In unit tests for tm/core, mock only external I/O (Supabase, APIs, filesystem) and use real internal services
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Separate core business logic from file system operations to enable deterministic testing
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:57:31.417Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-11-24T17:57:31.417Z
Learning: Applies to scripts/modules/task-manager/*.js, scripts/modules/commands.js : Be aware of potential reliability issues with `generateObjectService` across different providers and complex schemas; prefer `generateTextService` + manual parsing for robustness
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.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). (2)
- GitHub Check: Test
- GitHub Check: Cursor Bugbot
🔇 Additional comments (5)
.changeset/fix-file-locking.md (1)
1-13: Changeset accurately documents the fix.The changeset clearly describes the race condition fix and the key implementation details. All mentioned features align with the code changes across the repository.
scripts/modules/utils.js (1)
1803-1806: New locking utilities properly exported.The
withFileLockandwithFileLockSyncfunctions are correctly exported and available for use by other modules, as intended by the PR objectives.packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (3)
78-121: Excellent implementation of read-modify-write pattern.The
modifyJsonmethod correctly prevents lost updates by:
- Acquiring the lock (line 94)
- Re-reading current file state inside the lock (lines 96-105)
- Applying the modifier function (line 108)
- Writing atomically (line 111)
- Safely releasing the lock (lines 113-119)
This is the proper pattern for concurrent modifications and addresses the concerns from past reviews about stale updates.
140-160: Atomic write implementation is correct.Using a PID-suffixed temporary file (line 141) prevents collisions when multiple processes write concurrently. The rename operation (line 149) is atomic, and error cleanup (lines 151-156) is properly handled.
162-249: File operation helpers are correctly implemented.The helper methods (
exists,getStats,readDir,ensureDir,deleteFile,moveFile,copyFile,cleanup) are straightforward wrappers with appropriate error handling. ThedeleteFilemethod correctly ignores ENOENT errors (line 208).
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @scripts/modules/utils.js:
- Around line 42-51: The pre-check using fs.existsSync causes a TOCTOU race when
creating the file in withFileLock; replace the non-atomic create with an atomic
open/write using fs.openSync(filepath, 'wx') (or async fs.open with flag 'wx')
after ensuring the directory exists (mkdirSync(dir, { recursive: true })), write
the initial '{}' and close the descriptor, and swallow EEXIST errors (which
indicate another process created the file) while propagating other errors; keep
this logic inside withFileLock before acquiring the lock so multiple processes
race-safe attempt creation.
🧹 Nitpick comments (1)
scripts/modules/utils.js (1)
852-1010: LGTM! Robust atomic write implementation with proper locking.The function correctly:
- Uses
withFileLockSyncfor cross-process safety- Re-reads the file inside the lock to prevent lost updates from stale snapshots (lines 916-927)
- Performs atomic writes via PID-suffixed temp files with cleanup on failure
- Handles both tagged and untagged data formats
The metadata cleanup logic (lines 945-987) is complex but preserves backward compatibility by moving root-level properties into the metadata object.
♻️ Optional: Extract metadata cleanup into a helper function
Consider extracting the metadata cleanup logic (lines 952-986) into a separate function for better testability and maintainability:
/** * Clean up tag object by moving root-level metadata to metadata property */ function cleanupTagMetadata(tagData) { if (!tagData || typeof tagData !== 'object' || !Array.isArray(tagData.tasks)) { return tagData; } const { created, description, ...cleanTagData } = tagData; if (!cleanTagData.metadata) { cleanTagData.metadata = {}; } if (created && !cleanTagData.metadata.created) { cleanTagData.metadata.created = created; } if (description && !cleanTagData.metadata.description) { cleanTagData.metadata.description = description; } return cleanTagData; }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.js
🧰 Additional context used
📓 Path-based instructions (10)
scripts/modules/utils.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
When adding utilities to
utils.js, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Files:
scripts/modules/utils.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
**/*.js: Always use isSilentMode() function to check current silent mode status instead of directly accessing the global silentMode variable or global.silentMode
Use try/finally block pattern when wrapping core function calls with enableSilentMode/disableSilentMode to ensure silent mode is always restored, even if errors occur
For functions that need to handle both a passed silentMode parameter and check global state, check both the function parameter and global state: const isSilent = options.silentMode || (typeof options.silentMode === 'undefined' && isSilentMode())
Functions should accept their dependencies as parameters rather than using globals to promote testability and explicit dependency injection
Define callbacks as separate functions for easier testing rather than inline functions
Files:
scripts/modules/utils.js
scripts/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/context_gathering.mdc)
scripts/**/*.js: Use theContextGathererclass fromscripts/modules/utils/contextGatherer.jsto extract context from multiple sources (tasks, files, custom text, project tree) with token counting usinggpt-tokenslibrary
InitializeContextGathererwith project root and tasks path, then callgather()method with tasks array, files array, customContext, includeProjectTree, format ('research', 'chat', or 'system-prompt'), and includeTokenCounts options
Use theFuzzyTaskSearchclass fromscripts/modules/utils/fuzzyTaskSearch.jsfor intelligent task discovery with semantic matching, purpose categorization, and relevance scoring using Fuse.js
Implement a three-step initialization pattern for context-aware commands: (1) validate and parse parameters, (2) initialize context gatherer and find project root, (3) auto-discover relevant tasks using fuzzy search if task IDs not specified
Display token breakdown usingboxenlibrary with sections for tasks, files, and prompts, showing formatted token counts and file sizes in a clean bordered box with title
Process AI result responses usingcli-highlightlibrary to apply syntax highlighting to code blocks with language detection in the formatlanguage\ncode
Set reasonable file size limits (50KB default) and project tree depth limits (3-5 levels) when gathering context to maintain performance
Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior
Files:
scripts/modules/utils.js
scripts/modules/**/*
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
Restart the MCP server if core logic in
scripts/modulesor MCP tool definitions change
Files:
scripts/modules/utils.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/mcp.mdc)
When implementing MCP support for a command, ensure the core logic function can suppress console output via an outputFormat parameter or other mechanism
scripts/modules/*.js: Use consistent file naming conventions:task_${id.toString().padStart(3, '0')}.txtfor task files; usepath.join()for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
UseisSilentMode()function to check global silent mode status; wrap core function calls within direct functions usingenableSilentMode()anddisableSilentMode()in try/finally blocks if the core function produces console output not reliably controlled by outputFormat parameter
Ensure AI calls correctly handle and propagatetelemetryDataas described intelemetry.mdc
Import context gathering utilities (ContextGatherer,FuzzyTaskSearch) for AI-powered commands; support multiple context types (tasks, files, custom text, project tree); implement detailed token breakdown display
PrefergenerateTextServicefor calls sending large context (like stringified JSON) where incremental display is not needed; import necessary service functions fromai-services-unified.jsand prepare parameters (role, session, systemPrompt, prompt)
Create a clear unidirectional flow of dependencies between modules; separate business logic from UI rendering to avoid circular dependencies
Design functions to accept dependencies as parameters; avoid hard-coded dependencies that are difficult to mock
Keep pure logic separate from I/O operations or UI rendering to allow testing logic without mocking complex dependencies
Design core logic to work wi...
Files:
scripts/modules/utils.js
**/*.{js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
JavaScript test files using Jest must follow the same testing patterns as TypeScript files, include proper mocking of external dependencies, and achieve the same coverage thresholds
Files:
scripts/modules/utils.js
**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements
Files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
scripts/modules/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
scripts/modules/**/*.{js,ts}: Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
When a logger object is passed as a parameter to core functions, ensure the receiving function can call methods like .info, .warn, .error on that object
Files:
scripts/modules/utils.js
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Import modules with
.jsextension even in TypeScript source files for ESM compatibility
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧠 Learnings (48)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/**/CLAUDE.md : Update `CLAUDE.md` file with project-specific context, task summaries, and custom command examples for Claude Code integration
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1194
File: .github/workflows/ci.yml:31-35
Timestamp: 2025-09-09T19:13:55.652Z
Learning: The claude-task-master project has only one package-lock.json file in the entire workspace (at the root level), so cache-dependency-path configuration is unnecessary for the npm cache in GitHub Actions.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use findTasksJsonPath utility within direct functions to locate the tasks.json file consistently
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Create utilities for consistent task ID handling that support different ID formats (numeric, string, dot notation)
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/context_gathering.mdc:0-0
Timestamp: 2025-11-24T17:59:00.056Z
Learning: Applies to scripts/**/*.js : Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Place utilities used primarily by the core task-master CLI logic and command modules into scripts/modules/utils.js
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/utils.js : When adding utilities to `utils.js`, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys with helpful hints for fallbacks
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Design core logic to work with both legacy (flat tasks array) and tagged task data formats; use tag resolution functions (getTasksForTag, setTasksForTag) for task data access; support silent migration during feature usage
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : In MCP direct functions, support explicit tag specification and use tag resolution for task data operations; default to current tag when not specified
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : For file path handling in destructive operations: use path.join() to construct paths, follow naming conventions (e.g., task_001.txt), check file existence before deletion, and handle errors gracefully without string concatenation
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-08-06T21:12:43.715Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-orchestrator.md:1-6
Timestamp: 2025-08-06T21:12:43.715Z
Learning: In the eyaltoledano/claude-task-master repository, agent files are intentionally duplicated between `.claude/agents/` (for internal project use) and `assets/claude/agents/` (as template files for users to copy). This duplication serves different purposes and should be maintained to support both internal development and user distribution needs.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-08-06T21:12:20.981Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-executor.md:1-6
Timestamp: 2025-08-06T21:12:20.981Z
Learning: In the eyaltoledano/claude-task-master repository, agent files in assets/claude/agents/ are intended for distribution to users (for copying), while identical files in .claude/agents/ are for internal project use. This intentional duplication serves different purposes and is not a DRY violation.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/task-manager.js : Data manipulation features (create, read, update, delete tasks) should be placed in `task-manager.js` and follow guidelines in `tasks.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/commands/**/*.{js,ts} : Handle potential ConfigurationError if the .taskmasterconfig file is missing or invalid when accessed via getConfig
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use consistent file naming conventions: `task_${id.toString().padStart(3, '0')}.txt` for task files; use `path.join()` for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks and self-references during cleanup, tracking and reporting changes made during cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI within the current tag context (defaulting to "master"), providing clear prompts to guide AI task generation and validating/cleaning up AI-generated tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data after destructive operations, handling both direct and indirect references with explanatory console logging
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data, handle both direct and indirect references, and explain what related data is being updated.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks during cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Track and report changes made during dependency cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys for features that depend on them.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Pass context object `{ projectRoot, tag }` to all core functions that read or write tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T05:38:17.352Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 943
File: scripts/modules/task-manager/move-task.js:24-24
Timestamp: 2025-07-18T05:38:17.352Z
Learning: In the Claude Task Master system, core task-manager functions are designed with fallback mechanisms for missing projectRoot parameters using the pattern `const projectRoot = providedProjectRoot || findProjectRoot();`. The readJSON and writeJSON functions have default parameters (projectRoot = null, tag = null) and handle missing parameters gracefully. Adding strict validation to these core functions would break the established flexible architecture pattern.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Core task functions must accept a context parameter with `{ projectRoot, tag }` properties
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Implement silent migration in readJSON() function to automatically convert legacy tasks.json format ({"tasks": [...]}) to tagged format ({"master": {"tasks": [...]}}) on first use while preserving all existing task data
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Implement reusable task finding utilities that support both task and subtask lookups and add context to subtask results
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent properties for subtasks (id, title, description, status, dependencies, details) without duplicating parent task properties, maintaining simple numeric IDs unique within the parent task
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Include all required task properties (id, title, description, status, dependencies, priority, details, testStrategy, subtasks) in each task object without adding extra properties outside the standard schema
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to packages/tm-core/**/*.{spec,test}.ts : In unit tests for tm/core, mock only external I/O (Supabase, APIs, filesystem) and use real internal services
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Use try/catch blocks for all file operations and return null or a default value on failure rather than allowing exceptions to propagate unhandled
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use path.join() instead of string concatenation for file paths, follow established file naming conventions (task_001.txt format), and use path.dirname() and related path utilities for manipulating paths
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Log detailed error information using the log utility in catch blocks for file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.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). (2)
- GitHub Check: Test
- GitHub Check: Cursor Bugbot
🔇 Additional comments (8)
scripts/modules/utils.js (3)
10-10: LGTM! Well-configured locking options.The locking configuration is appropriate with a 10-second stale timeout and exponential backoff retry strategy. The
realpath: falseoptimization avoids unnecessary symlink resolution.Also applies to: 24-33
1819-1821: LGTM! Locking utilities properly exported.The new cross-process locking utilities are correctly exported for reuse by other modules, following the project's utility export conventions.
135-140: Atomics.wait is fully compatible with the specified Node.js version requirement.The project requires Node.js >=20.0.0 (per package.json), which fully supports
Atomics.waitandSharedArrayBuffer. The synchronous sleep implementation is appropriate and compatible with all supported versions.packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (5)
7-8: LGTM! Consistent locking configuration.The locking configuration matches the implementation in
scripts/modules/utils.js, ensuring consistent behavior across the codebase. Good use of thenode:prefix for built-in imports.Also applies to: 14-23
51-76: LGTM! Well-documented atomic write with locking.The function correctly:
- Documents the warning about full file replacement and recommends
modifyJson()for concurrent modifications- Ensures file existence before locking
- Acquires cross-process lock and performs atomic write
- Safely releases lock with error handling in finally block
78-121: Excellent! Proper read-modify-write pattern.This is a best-practice implementation that:
- Re-reads the file INSIDE the lock to prevent lost updates from stale snapshots (lines 96-105)
- Supports both synchronous and asynchronous modifier functions
- Handles missing/invalid files gracefully
- Performs atomic writes with proper lock management
This pattern should be preferred over
writeJson()when multiple processes might modify the same file concurrently.
123-139: LGTM! Atomic file creation prevents TOCTOU races.The use of the
'wx'flag ensures atomic file creation, preventing time-of-check-to-time-of-use race conditions. TheEEXISThandling correctly tolerates the file being created by another process.
145-145: Good improvement! PID-suffixed temp files reduce collision risk.Using
process.pidin the temp filename prevents collisions when multiple processes write to the same file simultaneously. Each process gets its own temp file, and the atomic rename ensures consistency.
There was a problem hiding this comment.
nice initiative, we use steno for fire locking, maybe try using that instead ?
steno
see an example of how we use it in:
packages/tm-core/src/modules/workflow/managers/workflow-state-manager.ts
Also, make sure that any new code is written in typescript inside packages/* (it can be added in tm-bridge if you can't put it in tm-core) so that we are gradually transitioning into a typescript codebase and moving away from javascript for type safety
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (1)
96-102: Consider logging or differentiating between empty file vs. corrupted file.The catch block at lines 99-102 treats both empty files and parse errors the same way (starting fresh with
{}). For corrupted JSON, this could silently discard data.♻️ Suggested improvement to differentiate error cases
try { const content = await fs.readFile(filePath, 'utf-8'); + if (content.trim() === '') { + currentData = {} as T; + } else { - currentData = JSON.parse(content); + currentData = JSON.parse(content); + } } catch { - // File empty or invalid - start with empty object + // Parse error - log warning but continue with empty object + // This prevents blocking on corrupted files while alerting developers + console.warn(`Warning: Could not parse ${filePath}, starting fresh`); currentData = {} as T; }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (2)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.js
🧰 Additional context used
📓 Path-based instructions (10)
scripts/modules/utils.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
When adding utilities to
utils.js, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Files:
scripts/modules/utils.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
**/*.js: Always use isSilentMode() function to check current silent mode status instead of directly accessing the global silentMode variable or global.silentMode
Use try/finally block pattern when wrapping core function calls with enableSilentMode/disableSilentMode to ensure silent mode is always restored, even if errors occur
For functions that need to handle both a passed silentMode parameter and check global state, check both the function parameter and global state: const isSilent = options.silentMode || (typeof options.silentMode === 'undefined' && isSilentMode())
Functions should accept their dependencies as parameters rather than using globals to promote testability and explicit dependency injection
Define callbacks as separate functions for easier testing rather than inline functions
Files:
scripts/modules/utils.js
scripts/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/context_gathering.mdc)
scripts/**/*.js: Use theContextGathererclass fromscripts/modules/utils/contextGatherer.jsto extract context from multiple sources (tasks, files, custom text, project tree) with token counting usinggpt-tokenslibrary
InitializeContextGathererwith project root and tasks path, then callgather()method with tasks array, files array, customContext, includeProjectTree, format ('research', 'chat', or 'system-prompt'), and includeTokenCounts options
Use theFuzzyTaskSearchclass fromscripts/modules/utils/fuzzyTaskSearch.jsfor intelligent task discovery with semantic matching, purpose categorization, and relevance scoring using Fuse.js
Implement a three-step initialization pattern for context-aware commands: (1) validate and parse parameters, (2) initialize context gatherer and find project root, (3) auto-discover relevant tasks using fuzzy search if task IDs not specified
Display token breakdown usingboxenlibrary with sections for tasks, files, and prompts, showing formatted token counts and file sizes in a clean bordered box with title
Process AI result responses usingcli-highlightlibrary to apply syntax highlighting to code blocks with language detection in the formatlanguage\ncode
Set reasonable file size limits (50KB default) and project tree depth limits (3-5 levels) when gathering context to maintain performance
Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior
Files:
scripts/modules/utils.js
scripts/modules/**/*
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
Restart the MCP server if core logic in
scripts/modulesor MCP tool definitions change
Files:
scripts/modules/utils.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/mcp.mdc)
When implementing MCP support for a command, ensure the core logic function can suppress console output via an outputFormat parameter or other mechanism
scripts/modules/*.js: Use consistent file naming conventions:task_${id.toString().padStart(3, '0')}.txtfor task files; usepath.join()for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
UseisSilentMode()function to check global silent mode status; wrap core function calls within direct functions usingenableSilentMode()anddisableSilentMode()in try/finally blocks if the core function produces console output not reliably controlled by outputFormat parameter
Ensure AI calls correctly handle and propagatetelemetryDataas described intelemetry.mdc
Import context gathering utilities (ContextGatherer,FuzzyTaskSearch) for AI-powered commands; support multiple context types (tasks, files, custom text, project tree); implement detailed token breakdown display
PrefergenerateTextServicefor calls sending large context (like stringified JSON) where incremental display is not needed; import necessary service functions fromai-services-unified.jsand prepare parameters (role, session, systemPrompt, prompt)
Create a clear unidirectional flow of dependencies between modules; separate business logic from UI rendering to avoid circular dependencies
Design functions to accept dependencies as parameters; avoid hard-coded dependencies that are difficult to mock
Keep pure logic separate from I/O operations or UI rendering to allow testing logic without mocking complex dependencies
Design core logic to work wi...
Files:
scripts/modules/utils.js
**/*.{js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
JavaScript test files using Jest must follow the same testing patterns as TypeScript files, include proper mocking of external dependencies, and achieve the same coverage thresholds
Files:
scripts/modules/utils.js
**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements
Files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
scripts/modules/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
scripts/modules/**/*.{js,ts}: Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
When a logger object is passed as a parameter to core functions, ensure the receiving function can call methods like .info, .warn, .error on that object
Files:
scripts/modules/utils.js
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Import modules with
.jsextension even in TypeScript source files for ESM compatibility
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧠 Learnings (51)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/**/CLAUDE.md : Update `CLAUDE.md` file with project-specific context, task summaries, and custom command examples for Claude Code integration
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1194
File: .github/workflows/ci.yml:31-35
Timestamp: 2025-09-09T19:13:55.652Z
Learning: The claude-task-master project has only one package-lock.json file in the entire workspace (at the root level), so cache-dependency-path configuration is unnecessary for the npm cache in GitHub Actions.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Place utilities used primarily by the core task-master CLI logic and command modules into scripts/modules/utils.js
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Export all utility functions explicitly in logical groups and include configuration constants from utility modules
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:59:00.056Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/context_gathering.mdc:0-0
Timestamp: 2025-11-24T17:59:00.056Z
Learning: Applies to scripts/modules/utils/{contextGatherer,fuzzyTaskSearch}.js : Export utility modules using named exports: `ContextGatherer`, `createContextGatherer` from contextGatherer.js and `FuzzyTaskSearch`, `PURPOSE_CATEGORIES`, `RELEVANCE_THRESHOLDS` from fuzzyTaskSearch.js
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Design core logic to work with both legacy (flat tasks array) and tagged task data formats; use tag resolution functions (getTasksForTag, setTasksForTag) for task data access; support silent migration during feature usage
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : In MCP direct functions, support explicit tag specification and use tag resolution for task data operations; default to current tag when not specified
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : For file path handling in destructive operations: use path.join() to construct paths, follow naming conventions (e.g., task_001.txt), check file existence before deletion, and handle errors gracefully without string concatenation
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-08-06T21:12:43.715Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-orchestrator.md:1-6
Timestamp: 2025-08-06T21:12:43.715Z
Learning: In the eyaltoledano/claude-task-master repository, agent files are intentionally duplicated between `.claude/agents/` (for internal project use) and `assets/claude/agents/` (as template files for users to copy). This duplication serves different purposes and should be maintained to support both internal development and user distribution needs.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-08-06T21:12:20.981Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-executor.md:1-6
Timestamp: 2025-08-06T21:12:20.981Z
Learning: In the eyaltoledano/claude-task-master repository, agent files in assets/claude/agents/ are intended for distribution to users (for copying), while identical files in .claude/agents/ are for internal project use. This intentional duplication serves different purposes and is not a DRY violation.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/task-manager.js : Data manipulation features (create, read, update, delete tasks) should be placed in `task-manager.js` and follow guidelines in `tasks.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/commands/**/*.{js,ts} : Handle potential ConfigurationError if the .taskmasterconfig file is missing or invalid when accessed via getConfig
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use consistent file naming conventions: `task_${id.toString().padStart(3, '0')}.txt` for task files; use `path.join()` for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use path.join() instead of string concatenation for file paths, follow established file naming conventions (task_001.txt format), and use path.dirname() and related path utilities for manipulating paths
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks and self-references during cleanup, tracking and reporting changes made during cleanup
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data after destructive operations, handling both direct and indirect references with explanatory console logging
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI within the current tag context (defaulting to "master"), providing clear prompts to guide AI task generation and validating/cleaning up AI-generated tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data, handle both direct and indirect references, and explain what related data is being updated.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Track and report changes made during dependency cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys with helpful hints for fallbacks
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-09-03T13:46:00.640Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/auth/oauth-service.ts:20-20
Timestamp: 2025-09-03T13:46:00.640Z
Learning: For Node.js v22 and later, JSON imports should use `with { type: 'json' }` syntax, not `assert { type: 'json' }`. The `assert` syntax was removed in Node.js v22 in favor of the `with` syntax for import attributes. This applies to the eyaltoledano/claude-task-master codebase which uses Node.js v24.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T05:38:17.352Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 943
File: scripts/modules/task-manager/move-task.js:24-24
Timestamp: 2025-07-18T05:38:17.352Z
Learning: In the Claude Task Master system, core task-manager functions are designed with fallback mechanisms for missing projectRoot parameters using the pattern `const projectRoot = providedProjectRoot || findProjectRoot();`. The readJSON and writeJSON functions have default parameters (projectRoot = null, tag = null) and handle missing parameters gracefully. Adding strict validation to these core functions would break the established flexible architecture pattern.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Ensure AI calls correctly handle and propagate `telemetryData` as described in `telemetry.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Use try/catch blocks for all file operations and return null or a default value on failure rather than allowing exceptions to propagate unhandled
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Pass context object `{ projectRoot, tag }` to all core functions that read or write tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Core task functions must accept a context parameter with `{ projectRoot, tag }` properties
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Implement silent migration in readJSON() function to automatically convert legacy tasks.json format ({"tasks": [...]}) to tagged format ({"master": {"tasks": [...]}}) on first use while preserving all existing task data
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Implement reusable task finding utilities that support both task and subtask lookups and add context to subtask results
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent properties for subtasks (id, title, description, status, dependencies, details) without duplicating parent task properties, maintaining simple numeric IDs unique within the parent task
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Include all required task properties (id, title, description, status, dependencies, priority, details, testStrategy, subtasks) in each task object without adding extra properties outside the standard schema
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to packages/tm-core/**/*.{spec,test}.ts : In unit tests for tm/core, mock only external I/O (Supabase, APIs, filesystem) and use real internal services
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Log detailed error information using the log utility in catch blocks for file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks during cleanup
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧬 Code graph analysis (1)
scripts/modules/utils.js (8)
scripts/modules/task-manager/update-task-by-id.js (2)
data(120-120)projectRoot(77-77)scripts/modules/task-manager/update-tasks.js (2)
data(75-75)projectRoot(69-69)scripts/modules/ui.js (5)
data(986-986)data(1266-1266)data(2380-2380)projectRoot(2376-2376)tag(2377-2377)mcp-server/src/core/direct-functions/clear-subtasks.js (1)
data(72-72)mcp-server/src/core/direct-functions/remove-task.js (1)
data(65-65)scripts/modules/commands.js (3)
projectRoot(425-425)projectRoot(5280-5280)tag(5276-5276)src/utils/path-utils.js (2)
projectRoot(77-77)tag(351-351)mcp-server/src/tools/utils.js (1)
projectRoot(247-249)
⏰ 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: Cursor Bugbot
🔇 Additional comments (12)
scripts/modules/utils.js (6)
22-32: LGTM - Lock configuration and sleep helper are well-defined.The configuration values are reasonable: 5 retries with 100ms base delay and 10s stale lock timeout provide good balance between responsiveness and avoiding race conditions.
186-191: Good use ofAtomics.wait()for synchronous sleep.This is the correct approach for non-busy-wait synchronous sleeping in Node.js, as noted in the comment. This is more efficient than
while(Date.now() < target) {}busy loops that would consume CPU.
915-995: Well-designed lock-protected read-modify-write pattern.The re-reading of the file inside the lock (lines 937-946 and 969-979) is crucial for preventing lost updates from stale snapshots. This correctly implements the fix for the race condition described in issue #1567.
The two branches handle:
- Edge case where
_rawTaggedDatawas lost (MCP path) - re-reads and merges- Normal case with
_rawTaggedData- re-reads current state instead of trusting potentially stale cached data
1041-1057: Correct atomic write implementation.The temp-file + rename pattern with PID-suffixed filenames ensures:
- No partial writes visible to readers
- No temp file collisions between concurrent processes
- Proper cleanup on write failure
1871-1873: Exports correctly updated.The new file locking utilities are properly exported for use by other modules. Based on coding guidelines,
utils.jsshould provide core utility functions including file I/O.
47-55: File creation behavior inwithFileLockis intentional and appropriate—no action needed.The '
wx' flag correctly ensures files are created only when they don't exist, preventing overwrites and race conditions. This behavior is explicitly tested (see test case "should create file if it does not exist") and is used exclusively bywriteJSONfor task file operations. No refactoring or documentation changes are required.Likely an incorrect or invalid review comment.
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (6)
14-23: Lock configuration is consistent withutils.jsimplementation.The 10-second stale timeout and retry configuration (5 retries with exponential backoff from 100ms) align with the custom implementation in
scripts/modules/utils.js, ensuring consistent behavior across both code paths.
48-73: Good design: explicit warning about concurrent modifications.The docstring correctly warns that
writeJson"replaces the entire file" and recommends usingmodifyJson()instead "to prevent lost updates." This is clearer than theutils.jsapproach which silently handles the re-read internally.The lock-ensure-write-release pattern is correctly implemented.
124-136: Correct atomic file creation pattern.The
'wx'flag ensures atomic file creation, and ignoringEEXISTerrors handles the expected race condition where another process created the file first. This mirrors the approach inutils.js.
141-161: Atomic write implementation is correct and consistent.The PID-suffixed temp file path and temp-file + rename pattern match the implementation in
utils.js, ensuring consistent atomic write behavior across both code paths.
241-246: No-op cleanup is appropriate for the new locking design.Since
proper-lockfilereleases locks immediately in thefinallyblocks of each operation, there's no accumulated state to clean up. Keeping the method maintains API compatibility.
8-8: Theproper-lockfilepackage (v4.1.2) is properly pinned with appropriate version constraints and has no known security vulnerabilities. No further action needed.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
scripts/modules/utils.js (1)
194-197: Minor: Unused error variable.The
renameErrvariable is caught but not used. Consider using an empty catch block or adding an underscore prefix for clarity.💡 Optional: Remove unused variable
- } catch (renameErr) { + } catch { // Rename failed - another process handled it or lock was refreshed // Just continue to retry }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
scripts/modules/utils.js
🧰 Additional context used
📓 Path-based instructions (8)
scripts/modules/utils.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
When adding utilities to
utils.js, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Files:
scripts/modules/utils.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
**/*.js: Always use isSilentMode() function to check current silent mode status instead of directly accessing the global silentMode variable or global.silentMode
Use try/finally block pattern when wrapping core function calls with enableSilentMode/disableSilentMode to ensure silent mode is always restored, even if errors occur
For functions that need to handle both a passed silentMode parameter and check global state, check both the function parameter and global state: const isSilent = options.silentMode || (typeof options.silentMode === 'undefined' && isSilentMode())
Functions should accept their dependencies as parameters rather than using globals to promote testability and explicit dependency injection
Define callbacks as separate functions for easier testing rather than inline functions
Files:
scripts/modules/utils.js
scripts/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/context_gathering.mdc)
scripts/**/*.js: Use theContextGathererclass fromscripts/modules/utils/contextGatherer.jsto extract context from multiple sources (tasks, files, custom text, project tree) with token counting usinggpt-tokenslibrary
InitializeContextGathererwith project root and tasks path, then callgather()method with tasks array, files array, customContext, includeProjectTree, format ('research', 'chat', or 'system-prompt'), and includeTokenCounts options
Use theFuzzyTaskSearchclass fromscripts/modules/utils/fuzzyTaskSearch.jsfor intelligent task discovery with semantic matching, purpose categorization, and relevance scoring using Fuse.js
Implement a three-step initialization pattern for context-aware commands: (1) validate and parse parameters, (2) initialize context gatherer and find project root, (3) auto-discover relevant tasks using fuzzy search if task IDs not specified
Display token breakdown usingboxenlibrary with sections for tasks, files, and prompts, showing formatted token counts and file sizes in a clean bordered box with title
Process AI result responses usingcli-highlightlibrary to apply syntax highlighting to code blocks with language detection in the formatlanguage\ncode
Set reasonable file size limits (50KB default) and project tree depth limits (3-5 levels) when gathering context to maintain performance
Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior
Files:
scripts/modules/utils.js
scripts/modules/**/*
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
Restart the MCP server if core logic in
scripts/modulesor MCP tool definitions change
Files:
scripts/modules/utils.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/mcp.mdc)
When implementing MCP support for a command, ensure the core logic function can suppress console output via an outputFormat parameter or other mechanism
scripts/modules/*.js: Use consistent file naming conventions:task_${id.toString().padStart(3, '0')}.txtfor task files; usepath.join()for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
UseisSilentMode()function to check global silent mode status; wrap core function calls within direct functions usingenableSilentMode()anddisableSilentMode()in try/finally blocks if the core function produces console output not reliably controlled by outputFormat parameter
Ensure AI calls correctly handle and propagatetelemetryDataas described intelemetry.mdc
Import context gathering utilities (ContextGatherer,FuzzyTaskSearch) for AI-powered commands; support multiple context types (tasks, files, custom text, project tree); implement detailed token breakdown display
PrefergenerateTextServicefor calls sending large context (like stringified JSON) where incremental display is not needed; import necessary service functions fromai-services-unified.jsand prepare parameters (role, session, systemPrompt, prompt)
Create a clear unidirectional flow of dependencies between modules; separate business logic from UI rendering to avoid circular dependencies
Design functions to accept dependencies as parameters; avoid hard-coded dependencies that are difficult to mock
Keep pure logic separate from I/O operations or UI rendering to allow testing logic without mocking complex dependencies
Design core logic to work wi...
Files:
scripts/modules/utils.js
**/*.{js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
JavaScript test files using Jest must follow the same testing patterns as TypeScript files, include proper mocking of external dependencies, and achieve the same coverage thresholds
Files:
scripts/modules/utils.js
**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements
Files:
scripts/modules/utils.js
scripts/modules/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
scripts/modules/**/*.{js,ts}: Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
When a logger object is passed as a parameter to core functions, ensure the receiving function can call methods like .info, .warn, .error on that object
Files:
scripts/modules/utils.js
🧠 Learnings (46)
📓 Common learnings
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/**/CLAUDE.md : Update `CLAUDE.md` file with project-specific context, task summaries, and custom command examples for Claude Code integration
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Every command that reads or writes tasks.json must be tag-aware and support the tagged task lists system
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use findTasksJsonPath utility within direct functions to locate the tasks.json file consistently
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/dependency-manager.js : dependency-manager.js should manage task dependencies by handling add/remove/validate/fix operations across tagged task contexts
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Place utilities used primarily by the core task-master CLI logic and command modules into scripts/modules/utils.js
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Export all utility functions explicitly in logical groups and include configuration constants from utility modules
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Design core logic to work with both legacy (flat tasks array) and tagged task data formats; use tag resolution functions (getTasksForTag, setTasksForTag) for task data access; support silent migration during feature usage
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : In MCP direct functions, support explicit tag specification and use tag resolution for task data operations; default to current tag when not specified
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : For file path handling in destructive operations: use path.join() to construct paths, follow naming conventions (e.g., task_001.txt), check file existence before deletion, and handle errors gracefully without string concatenation
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-08-06T21:12:43.715Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-orchestrator.md:1-6
Timestamp: 2025-08-06T21:12:43.715Z
Learning: In the eyaltoledano/claude-task-master repository, agent files are intentionally duplicated between `.claude/agents/` (for internal project use) and `assets/claude/agents/` (as template files for users to copy). This duplication serves different purposes and should be maintained to support both internal development and user distribution needs.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-08-06T21:12:20.981Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-executor.md:1-6
Timestamp: 2025-08-06T21:12:20.981Z
Learning: In the eyaltoledano/claude-task-master repository, agent files in assets/claude/agents/ are intended for distribution to users (for copying), while identical files in .claude/agents/ are for internal project use. This intentional duplication serves different purposes and is not a DRY violation.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/task-manager.js : Data manipulation features (create, read, update, delete tasks) should be placed in `task-manager.js` and follow guidelines in `tasks.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/commands/**/*.{js,ts} : Handle potential ConfigurationError if the .taskmasterconfig file is missing or invalid when accessed via getConfig
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use consistent file naming conventions: `task_${id.toString().padStart(3, '0')}.txt` for task files; use `path.join()` for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use path.join() instead of string concatenation for file paths, follow established file naming conventions (task_001.txt format), and use path.dirname() and related path utilities for manipulating paths
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks and self-references during cleanup, tracking and reporting changes made during cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data after destructive operations, handling both direct and indirect references with explanatory console logging
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI within the current tag context (defaulting to "master"), providing clear prompts to guide AI task generation and validating/cleaning up AI-generated tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data, handle both direct and indirect references, and explain what related data is being updated.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks during cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys with helpful hints for fallbacks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-09-03T13:46:00.640Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/auth/oauth-service.ts:20-20
Timestamp: 2025-09-03T13:46:00.640Z
Learning: For Node.js v22 and later, JSON imports should use `with { type: 'json' }` syntax, not `assert { type: 'json' }`. The `assert` syntax was removed in Node.js v22 in favor of the `with` syntax for import attributes. This applies to the eyaltoledano/claude-task-master codebase which uses Node.js v24.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T05:38:17.352Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 943
File: scripts/modules/task-manager/move-task.js:24-24
Timestamp: 2025-07-18T05:38:17.352Z
Learning: In the Claude Task Master system, core task-manager functions are designed with fallback mechanisms for missing projectRoot parameters using the pattern `const projectRoot = providedProjectRoot || findProjectRoot();`. The readJSON and writeJSON functions have default parameters (projectRoot = null, tag = null) and handle missing parameters gracefully. Adding strict validation to these core functions would break the established flexible architecture pattern.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Ensure AI calls correctly handle and propagate `telemetryData` as described in `telemetry.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Use try/catch blocks for all file operations and return null or a default value on failure rather than allowing exceptions to propagate unhandled
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Pass context object `{ projectRoot, tag }` to all core functions that read or write tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Core task functions must accept a context parameter with `{ projectRoot, tag }` properties
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Implement silent migration in readJSON() function to automatically convert legacy tasks.json format ({"tasks": [...]}) to tagged format ({"master": {"tasks": [...]}}) on first use while preserving all existing task data
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Implement reusable task finding utilities that support both task and subtask lookups and add context to subtask results
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent properties for subtasks (id, title, description, status, dependencies, details) without duplicating parent task properties, maintaining simple numeric IDs unique within the parent task
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Include all required task properties (id, title, description, status, dependencies, priority, details, testStrategy, subtasks) in each task object without adding extra properties outside the standard schema
Applied to files:
scripts/modules/utils.js
⏰ 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). (2)
- GitHub Check: Test
- GitHub Check: Cursor Bugbot
🔇 Additional comments (9)
scripts/modules/utils.js (9)
22-27: LGTM! Configuration constants are reasonable.The lock configuration provides sensible defaults: 5 retries with exponential backoff (total max wait ~3.1s) and 10s stale lock detection aligns with PR objectives.
29-32: LGTM!Standard async sleep implementation using Promise-wrapped setTimeout.
41-134: Well-designed async file locking implementation.The implementation correctly uses:
- Atomic file creation (
wxflag) for both the target file and lock file- Exponential backoff for retries
- Atomic rename for safe stale lock takeover (prevents race where we delete another process's fresh lock)
try/finallypattern to ensure lock releaseOne consideration: if a process crashes while holding the lock, the lock persists until stale detection (10s). This is expected behavior for file-based locking and documented in the PR objectives.
207-214: Good use ofAtomics.wait()for synchronous sleep.This is a proper non-busy wait mechanism, which is significantly better than a busy-wait loop for synchronous blocking. This aligns with the PR objective to replace busy-wait with
Atomics.wait().
985-1016: Critical fix: Re-reading file under lock prevents lost updates.This is the key fix for the race condition. By re-reading the file inside the lock rather than using the potentially stale
_rawTaggedData, the implementation ensures that concurrent writes from other processes aren't lost. The fallback to_rawTaggedDatawhen the file can't be read is acceptable since the lock prevents concurrent writes at that point.
1063-1079: Atomic write pattern correctly implemented.Writing to a temp file first and then atomically renaming it prevents partial writes from corrupting the file. The cleanup of the temp file on failure is also handled correctly.
1029-1058: Metadata normalization logic is correct.The cleanup logic properly moves root-level
createdanddescriptionproperties into themetadataobject, but only if the metadata doesn't already have these fields. This preserves existing metadata while ensuring consistent structure.
1893-1895: LGTM! New utilities correctly exported.The locking utilities
withFileLockandwithFileLockSyncare now publicly available as mentioned in the PR objectives.
136-143: No action needed:Atomics.wait()is fully supported and compatible.The project requires Node.js >=20.0.0 (per package.json), which well exceeds the v16+ threshold where
Atomics.wait()on the main thread is fully supported without flags. The implementation inwithFileLockSync()is compatible with the target Node.js version.Likely an incorrect or invalid review comment.
|
Thanks for the feedback @Crunchyman-ralph! I've updated the TypeScript implementation to use Changes made:
Note on approach:
The original bug report was about data loss when multiple Claude Code windows write to tasks.json at the same time. Since these are separate processes, we need cross-process locking to prevent the "lost update" problem where:
The combination of steno (for atomic writes) + proper-lockfile (for cross-process locking) + re-read inside lock (to get current state) provides comprehensive protection. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
@packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts:
- Around line 33-46: The writers Map is caching Writer instances forever and
cleanup() is a no-op; update the FileOperations cleanup implementation to
iterate the writers Map and properly close or end each steno Writer (call the
Writer's close/end/destroy/flush method available in your steno version),
handle/await any async close results, and then clear the writers Map; also
ensure getWriter still registers new Writers and that any code creating a writer
on demand can handle closed writers being removed so file handles and memory are
released.
🧹 Nitpick comments (2)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (2)
66-97: LGTM! Proper cross-process locking for atomic writes.The implementation correctly:
- Ensures file exists before locking (proper-lockfile requirement)
- Uses try-finally to guarantee lock release
- Employs steno Writer for atomic writes
- Warns callers about lost updates if not using modifyJson
Optional: Consider logging ignored lock release errors for debugging:
📝 Proposed logging addition
} catch { - // Ignore release errors - lock may have been released already + // Ignore release errors - lock may have been released already + // Could add logging here if debugging lock issues }
99-145: LGTM! Correct read-modify-write pattern prevents lost updates.The implementation correctly:
- Re-reads file inside the lock to prevent stale snapshot overwrites (line 118-127)
- Applies the modifier to fresh data
- Writes atomically via steno Writer
- Guarantees lock release even if modifier throws
Optional type safety improvement: The
{} as Tfallback (line 126) may be unsafe for non-object types:🔧 Safer type handling
} catch { - // File empty or invalid - start with empty object - currentData = {} as T; + // File empty or invalid - start with empty object or throw + // Consider: throw new Error(`Cannot read ${filePath} for modification`); + currentData = {} as T; // Assumes T is always an object type }This depends on your API contract—if callers always expect object types, the current approach is fine.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Import modules with
.jsextension even in TypeScript source files for ESM compatibility
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧠 Learnings (16)
📓 Common learnings
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/**/CLAUDE.md : Update `CLAUDE.md` file with project-specific context, task summaries, and custom command examples for Claude Code integration
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/.claude/settings.json : Add Claude Code tool allowlist configuration in `.claude/settings.json` to include 'Edit', 'Bash(task-master *)', 'Bash(git commit:*)', 'Bash(git add:*)', 'Bash(npm run *)', and 'mcp__task_master_ai__*'
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Every command that reads or writes tasks.json must be tag-aware and support the tagged task lists system
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use findTasksJsonPath utility within direct functions to locate the tasks.json file consistently
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use path.join() instead of string concatenation for file paths, follow established file naming conventions (task_001.txt format), and use path.dirname() and related path utilities for manipulating paths
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Use try/catch blocks for all file operations and return null or a default value on failure rather than allowing exceptions to propagate unhandled
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : For file path handling in destructive operations: use path.join() to construct paths, follow naming conventions (e.g., task_001.txt), check file existence before deletion, and handle errors gracefully without string concatenation
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys with helpful hints for fallbacks
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use consistent file naming conventions: `task_${id.toString().padStart(3, '0')}.txt` for task files; use `path.join()` for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks and self-references during cleanup, tracking and reporting changes made during cleanup
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks during cleanup
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.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). (2)
- GitHub Check: Test
- GitHub Check: Cursor Bugbot
🔇 Additional comments (7)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (7)
1-14: LGTM! Clean imports with proper ESM conventions.The file header clearly documents the cross-process locking strategy, and imports follow ESM best practices with
.jsextensions in TypeScript.
48-64: LGTM! Appropriate error handling for JSON reads.The method correctly:
- Re-throws ENOENT for callers to handle (file doesn't exist)
- Wraps SyntaxError with context about which file failed
- Doesn't lock reads (intentional -
modifyJsonhandles atomic read-modify-write)
147-163: LGTM! Proper atomic file creation pattern.The implementation correctly:
- Uses
recursive: truefor directory creation (handles concurrent mkdir)- Employs
'wx'flag for atomic file creation (fails if file exists)- Handles expected EEXIST errors when another process wins the race
- Re-throws unexpected errors for visibility
The TOCTOU race is properly avoided by the atomic
'wx'flag.
165-202: LGTM! Clean utility methods with appropriate error handling.All methods follow Node.js best practices:
existsreturns boolean rather than throwingensureDirprovides contextual error messages- Simple wrappers around fs/promises for consistency
204-241: LGTM! Proper error handling in file operations.All methods correctly:
deleteFileignores ENOENT (idempotent deletion)moveFileandcopyFileprovide descriptive error messages with paths- Follow consistent error handling patterns
18-27: Configuration verified as correct. The LOCK_OPTIONS structure conforms to proper-lockfile v4.1.2 API:stale(10000ms) matches the library default and respects the 5000ms minimum;retriesis a valid retry options object with reasonable exponential backoff values (5 attempts, 100–1000ms range);realpath: falseis a valid performance optimization. No changes needed.
84-87: No changes needed — steno Writer API usage is correct.The implementation correctly uses steno v4.0.2's
WriterAPI: the constructor accepts a file path,write(content)returnsPromise<void>, and concurrent calls are automatically queued by steno. This matches the documented API signature and the pattern already used in workflow-state-manager.ts elsewhere in the codebase. No explicit cleanup/close is required—steno manages file handles automatically.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In
@packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts:
- Around line 33-46: FileStorage instances create FileOperations which cache
Writer objects via the writers Map in getWriter, and because
FileStorage.close()/cleanup() is not being called, the Writer cache grows and
leaks memory. Locate every place where new FileStorage(...) is instantiated
(e.g., the export command and service call sites) and wrap usage in try { ... }
finally { await fileStorage.close(); } (or ensure await fileStorage.close() is
called on all code paths) so FileOperations.cleanup() runs and Writers are
released.
- Around line 66-97: Several methods (saveTasks, createTag, deleteTag,
renameTag, copyTag) perform readJson() -> modify in-memory -> writeJson(),
causing lost updates; refactor each to call modifyJson(filePath, updater) so the
file is re-read and updated while the cross-process lock is held. For each
method, move the mutation logic into the updater callback passed to modifyJson,
returning the new data shape expected by the method (preserve existing return
values/IDs), and remove the separate readJson/writeJson calls; keep error
handling and edge-case checks inside the updater or immediately around
modifyJson to maintain original behavior.
🧹 Nitpick comments (1)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (1)
118-127: Consider more specific error handling for file read failures inside the lock.The catch-all on line 124 defaults to an empty object for ANY error, including permission errors, disk failures, or unexpected file system issues. While this may be acceptable since
ensureFileExists()was just called and the file is locked, being more specific would prevent masking unexpected errors.♻️ More specific error handling
// Re-read file INSIDE lock to get current state // This prevents lost updates from stale snapshots let currentData: T; try { const content = await fs.readFile(filePath, 'utf-8'); currentData = JSON.parse(content); -} catch { - // File empty or invalid - start with empty object +} catch (error: any) { + // If file is empty or has invalid JSON, start with empty object + // File should exist (we just ensured it) and be accessible (we hold the lock) + if (error instanceof SyntaxError || error.code === 'ENOENT') { + // Empty file or invalid JSON - acceptable + } else { + // Unexpected error (permission, disk, etc.) - log or rethrow + // For now, continue with empty object but consider logging + } currentData = {} as T; }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Import modules with
.jsextension even in TypeScript source files for ESM compatibility
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧠 Learnings (18)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/**/CLAUDE.md : Update `CLAUDE.md` file with project-specific context, task summaries, and custom command examples for Claude Code integration
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Every command that reads or writes tasks.json must be tag-aware and support the tagged task lists system
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use findTasksJsonPath utility within direct functions to locate the tasks.json file consistently
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Use try/catch blocks for all file operations and return null or a default value on failure rather than allowing exceptions to propagate unhandled
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use path.join() instead of string concatenation for file paths, follow established file naming conventions (task_001.txt format), and use path.dirname() and related path utilities for manipulating paths
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : For file path handling in destructive operations: use path.join() to construct paths, follow naming conventions (e.g., task_001.txt), check file existence before deletion, and handle errors gracefully without string concatenation
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys with helpful hints for fallbacks
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use consistent file naming conventions: `task_${id.toString().padStart(3, '0')}.txt` for task files; use `path.join()` for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks and self-references during cleanup, tracking and reporting changes made during cleanup
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks during cleanup
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Applies to tests/teardown.ts : Global teardown file must be created to handle cleanup after all tests complete and prevent worker process leaks
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Do not leave dangling references after deletion.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.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). (2)
- GitHub Check: Test
- GitHub Check: Cursor Bugbot
🔇 Additional comments (4)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (4)
147-163: LGTM! Race-condition-safe file creation.The use of the
'wx'flag ensures atomic file creation that fails if the file already exists, preventing TOCTOU race conditions between multiple processes. The EEXIST handling is correct—it's expected when another process creates the file first.
18-27: Remove this concern aboutrealpath: false.The codebase doesn't access tasks.json through symlinks. Path resolution uses explicit location checking in
src/utils/path-utils.js, and the only symlink-related code exists in test setup and directory traversal safety (unrelated to file locking). Settingrealpath: falsefor performance is appropriate.Likely an incorrect or invalid review comment.
11-12: Bothproper-lockfile(4.1.2) andsteno(4.0.2) are already at their latest stable versions with no known security vulnerabilities. No action required.
243-253: The steno Writer cleanup approach is correct. Steno v4.0.2 provides no explicit close() method and closes file descriptors automatically after each atomic write operation rather than keeping them open. Clearing thewritersMap is the appropriate cleanup strategy to allow Writer instances to be garbage collected, and the explanatory comment accurately reflects steno's internal resource management.
| /** Map of file paths to steno Writers for reuse */ | ||
| private writers = new Map<string, Writer>(); | ||
|
|
||
| /** | ||
| * Get or create a steno Writer for a file path | ||
| */ | ||
| private getWriter(filePath: string): Writer { | ||
| let writer = this.writers.get(filePath); | ||
| if (!writer) { | ||
| writer = new Writer(filePath); | ||
| this.writers.set(filePath, writer); | ||
| } | ||
| return writer; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find FileOperations class definition and cleanup method
find . -type f -name "*.ts" -o -name "*.js" | xargs grep -l "class FileOperations" 2>/dev/null || echo "Searching using fd..."
fd -t f "file-operations\." --search-path packages/tm-core/src/modules/storage/adapters/file-storage/Repository: eyaltoledano/claude-task-master
Length of output: 232
🏁 Script executed:
# Search for FileOperations instantiations
rg -n --type ts "new FileOperations\(" --context 3Repository: eyaltoledano/claude-task-master
Length of output: 865
🏁 Script executed:
# Search for cleanup() calls throughout the codebase
rg -n --type ts --type js "\.cleanup\(\)" --context 5Repository: eyaltoledano/claude-task-master
Length of output: 11351
🏁 Script executed:
# Look for disposal/lifecycle patterns with FileOperations
rg -n --type ts "FileOperations" --context 2 | head -100Repository: eyaltoledano/claude-task-master
Length of output: 3724
🏁 Script executed:
# Check if there's a dispose or destructor pattern in FileOperations
rg -n --type ts --type js "destroy|dispose|teardown" packages/tm-core/src/modules/storage/ --context 3Repository: eyaltoledano/claude-task-master
Length of output: 57
🏁 Script executed:
# Search for FileStorage instantiation
rg -n --type ts "new FileStorage\(" --context 5Repository: eyaltoledano/claude-task-master
Length of output: 6748
🏁 Script executed:
# Search for calls to .close() on storage or fileOps
rg -n --type ts "\.close\(\)" --context 3 | grep -A 3 -B 3 "FileStorage\|fileOps"Repository: eyaltoledano/claude-task-master
Length of output: 57
🏁 Script executed:
# Check if FileStorage is used in any resource cleanup patterns
rg -n --type ts "storage.*close\|await.*close" --context 2Repository: eyaltoledano/claude-task-master
Length of output: 57
🏁 Script executed:
# Look at the full cleanup method implementation
cat -n packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts | sed -n '243,260p'Repository: eyaltoledano/claude-task-master
Length of output: 574
Ensure FileStorage instances are properly closed to prevent Writer cache memory leaks.
FileStorage creates a FileOperations instance whose Writer cache will grow unbounded. While the cleanup() method exists, FileStorage.close() is never invoked in the actual codebase—instances are created but discarded without cleanup. This causes memory leaks in export.command.ts (lines 235, 393, 498, 719) and export.service.ts (lines 418, 844). Wrap FileStorage instantiation and usage in try/finally blocks that call await fileStorage.close().
🤖 Prompt for AI Agents
In
@packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
around lines 33 - 46, FileStorage instances create FileOperations which cache
Writer objects via the writers Map in getWriter, and because
FileStorage.close()/cleanup() is not being called, the Writer cache grows and
leaks memory. Locate every place where new FileStorage(...) is instantiated
(e.g., the export command and service call sites) and wrap usage in try { ... }
finally { await fileStorage.close(); } (or ensure await fileStorage.close() is
called on all code paths) so FileOperations.cleanup() runs and Writers are
released.
| /** | ||
| * Write JSON file with atomic operation and locking | ||
| * Write JSON file with atomic operation and cross-process locking. | ||
| * Uses steno for atomic writes and proper-lockfile for cross-process safety. | ||
| * WARNING: This replaces the entire file. For concurrent modifications, | ||
| * use modifyJson() instead to prevent lost updates. | ||
| */ | ||
| async writeJson( | ||
| filePath: string, | ||
| data: FileStorageData | any | ||
| ): Promise<void> { | ||
| // Use file locking to prevent concurrent writes | ||
| const lockKey = filePath; | ||
| const existingLock = this.fileLocks.get(lockKey); | ||
|
|
||
| if (existingLock) { | ||
| await existingLock; | ||
| } | ||
|
|
||
| const lockPromise = this.performAtomicWrite(filePath, data); | ||
| this.fileLocks.set(lockKey, lockPromise); | ||
| // Ensure file exists for locking (proper-lockfile requires this) | ||
| await this.ensureFileExists(filePath); | ||
|
|
||
| // Acquire cross-process lock | ||
| let release: (() => Promise<void>) | null = null; | ||
| try { | ||
| await lockPromise; | ||
| release = await lockfile.lock(filePath, LOCK_OPTIONS); | ||
|
|
||
| // Use steno Writer for atomic writes (same pattern as workflow-state-manager) | ||
| const content = JSON.stringify(data, null, 2); | ||
| const writer = this.getWriter(filePath); | ||
| await writer.write(content); | ||
| } finally { | ||
| this.fileLocks.delete(lockKey); | ||
| if (release) { | ||
| try { | ||
| await release(); | ||
| } catch { | ||
| // Ignore release errors - lock may have been released already | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all writeJson call sites with context
rg -n --type ts --type js -B 5 -A 5 '\.writeJson\('Repository: eyaltoledano/claude-task-master
Length of output: 7120
🏁 Script executed:
#!/bin/bash
# Look for patterns that might indicate read-modify-write
rg -n --type ts --type js -C 5 'readJson.*writeJson|writeJson.*readJson'Repository: eyaltoledano/claude-task-master
Length of output: 57
🏁 Script executed:
#!/bin/bash
# Also check for modifyJson usage to understand the pattern
rg -n --type ts --type js '\.modifyJson\('Repository: eyaltoledano/claude-task-master
Length of output: 57
🏁 Script executed:
#!/bin/bash
# Get more context around the writeJson calls - examine the methods they're in
rg -n --type ts 'async.*\(' packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts | head -30Repository: eyaltoledano/claude-task-master
Length of output: 1398
🏁 Script executed:
#!/bin/bash
# Check the specific methods containing these writeJson calls
sed -n '275,295p' packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.tsRepository: eyaltoledano/claude-task-master
Length of output: 485
🏁 Script executed:
#!/bin/bash
# Check for modifyJson definition and usage
rg -n --type ts 'modifyJson|async modifyJson' packages/tm-core/src/modules/storage/adapters/file-storage/Repository: eyaltoledano/claude-task-master
Length of output: 319
🏁 Script executed:
#!/bin/bash
# Look at the context more broadly for one of the writeJson calls
sed -n '270,295p' packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts
sed -n '630,680p' packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.tsRepository: eyaltoledano/claude-task-master
Length of output: 2056
🏁 Script executed:
#!/bin/bash
# Get the full saveTasks method (around line 224)
sed -n '224,310p' packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.tsRepository: eyaltoledano/claude-task-master
Length of output: 2447
🏁 Script executed:
#!/bin/bash
# Get the full createTag method (around line 598)
sed -n '598,685p' packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.tsRepository: eyaltoledano/claude-task-master
Length of output: 2411
🏁 Script executed:
#!/bin/bash
# Get modifyJson method signature and implementation
sed -n '106,150p' packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsRepository: eyaltoledano/claude-task-master
Length of output: 1396
Use modifyJson() for all read-modify-write operations to prevent lost updates in concurrent scenarios.
The implementation of modifyJson() (lines 106–150 in file-operations.ts) correctly re-reads the file inside the lock to prevent lost updates from stale snapshots. However, multiple methods in file-storage.ts (saveTasks, createTag, deleteTag, renameTag, copyTag) use the pattern of calling readJson() outside the lock, modifying the data, and then calling writeJson(). This creates a race condition where concurrent updates from other processes can be lost.
Refactor these methods to use modifyJson() with a callback function instead, ensuring all reads occur atomically within the cross-process lock.
🤖 Prompt for AI Agents
In
@packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
around lines 66 - 97, Several methods (saveTasks, createTag, deleteTag,
renameTag, copyTag) perform readJson() -> modify in-memory -> writeJson(),
causing lost updates; refactor each to call modifyJson(filePath, updater) so the
file is re-read and updated while the cross-process lock is held. For each
method, move the mutation logic into the updater callback passed to modifyJson,
returning the new data shape expected by the method (preserve existing return
values/IDs), and remove the separate readJson/writeJson calls; keep error
handling and edge-case checks inside the updater or immediately around
modifyJson to maintain original behavior.
Regarding CodeRabbit's Critical FeedbackThanks for the thorough analysis! Let me address both points: 1. FileStorage.close() not being calledThis is a pre-existing issue in the codebase that exists independently of this PR. My change actually adds functionality to 2. Using
|
Follow-up Issue CreatedI've created issue #1568 to track the broader work of adopting This PR (#1566) focuses on the immediate fix:
Issue #1568 covers the follow-up work:
This keeps the current PR focused and reduces risk of regressions. |
|
@bjcoombs lets fix the modifyJson issue in a separate PR, but maybe merge both at the same time ? |
Crunchyman-ralph
left a comment
There was a problem hiding this comment.
small question
Refactor file-storage.ts methods to use modifyJson instead of separate readJson/writeJson calls. This ensures the file is re-read inside the cross-process lock, preventing lost updates from stale snapshots. Methods updated: - saveTasks: Now uses modifyJson for atomic updates - createTag: Now uses modifyJson for atomic creation - deleteTag: Now uses modifyJson for legacy format deletion - renameTag: Now uses modifyJson for atomic renaming This complements the cross-process file locking from PR eyaltoledano#1566. Resolves issue eyaltoledano#1568.
|
@Crunchyman-ralph I've created the separate PR as requested: PR #1569: fix: adopt modifyJson pattern for atomic read-modify-write operations This PR depends on #1566 (it includes those changes via merge) and can be merged together as you suggested. Summary of both PRs:
|
Crunchyman-ralph
left a comment
There was a problem hiding this comment.
small question
0863bfd to
61407e4
Compare
Refactor file-storage.ts methods to use modifyJson instead of separate readJson/writeJson calls. This ensures the file is re-read inside the cross-process lock, preventing lost updates from stale snapshots. Methods updated: - saveTasks: Now uses modifyJson for atomic updates - createTag: Now uses modifyJson for atomic creation - deleteTag: Now uses modifyJson for legacy format deletion - renameTag: Now uses modifyJson for atomic renaming This complements the cross-process file locking from PR eyaltoledano#1566. Resolves issue eyaltoledano#1568.
There was a problem hiding this comment.
This PR is being reviewed by Cursor Bugbot
Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
When multiple Claude Code windows access tasks.json simultaneously, writes could be lost due to read-modify-write race conditions. Changes: - Add proper-lockfile dependency for cross-process locking - Implement withFileLock and withFileLockSync utilities - Update writeJSON to use file locking and atomic writes - Re-read file inside lock to prevent stale snapshot issues - Update tm-core FileOperations with cross-process locking - Add comprehensive tests for locking behavior The fix uses: 1. Lock file approach for cross-process synchronization 2. Atomic write pattern (temp file + rename) 3. Stale lock detection with 10 second timeout 4. Automatic retry with exponential backoff
- Remove unused fsSync import from file-operations.ts (TS6133) - Fix formatting: wrap long lines in utils.js - Fix formatting: apply biome formatting to test file and package.json
- Fix race condition in stale lock detection by wrapping statSync in try-catch - Replace busy-wait with Atomics.wait for proper non-blocking sync sleep - Add modifyJson() method for safe read-modify-write operations with re-read inside lock - Update writeJson() docs to warn about replacement behavior - Use consistent exponential backoff factor of 2 across async and sync paths
- Replace check-then-create with exclusive write ('wx' flag)
- If file already exists (EEXIST), that's fine - another process created it
- Fixes race where two processes both find file missing and both create it
- Fix retry count inconsistency: sync now uses 5 retries to match async - Fix metadata structure bug: metadata now properly nested in tag object - Preserve 'created' timestamp during cleanup (was being discarded) - Move root-level created/description into metadata during cleanup
- Add null check for data before accessing _rawTaggedData (cursor medium) - Unify async/sync lock mechanisms to use same lock file format (cursor high) - Both now create .lock file with JSON content (pid/timestamp) - Async uses fs.promises with proper async sleep - Removes proper-lockfile dependency from utils.js - Keep cleanup() method as no-op for API compatibility - Use shared LOCK_CONFIG for both async and sync locking
Fixes race condition where unlinking a stale lock could delete another process's fresh lock. Now uses atomic rename to take ownership: 1. Try to create lock with 'wx' (fails if exists) 2. If EEXIST, stat to check if stale 3. If stale, rename to unique path (atomic ownership transfer) 4. If rename succeeds, we own the stale lock - delete and retry 5. If rename fails, another process handled it - retry normally This ensures we never delete a lock we don't own.
Replace custom temp file + rename implementation with steno Writer for atomic writes, following the same pattern as workflow-state-manager.ts. - Import and use steno's Writer for atomic file writes - Keep proper-lockfile for cross-process locking (steno handles write atomicity within a process, but proper-lockfile is needed to prevent lost updates when multiple processes access the same file) - Remove custom performAtomicWrite method in favor of steno - Cache Writer instances per file path for reuse
Update cleanup() method to clear the cached Writers Map, allowing garbage collection of steno Writer instances in long-running processes. Addresses CodeRabbit feedback about unbounded Map growth in MCP servers and CLI daemons.
97d9401 to
7ed83e6
Compare
Crunchyman-ralph
left a comment
There was a problem hiding this comment.
lgtm, just needs to pass CI, and we merge
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @scripts/modules/utils.js:
- Around line 72-86: withFileLock currently unconditionally attempts to create
the target file (writeFile with flag 'wx'), which forces creation even for
read-only callers; change withFileLock to accept an options param (e.g.,
createIfMissing: boolean, default false) and only perform the atomic
fs.promises.writeFile(filepath, '{}', { flag: 'wx' }) when createIfMissing is
true, leaving file-not-found semantics intact for callers that expect to handle
missing files; update any call sites that rely on the previous behavior to pass
createIfMissing: true and add a short comment/docstring on withFileLock
describing the new option.
🧹 Nitpick comments (3)
scripts/modules/utils.js (2)
40-63: Consider documenting the busy-wait fallback limitation.The
Atomics.waitapproach is correct and preferred, but the busy-wait fallback at lines 59-62 will consume CPU cycles. While acceptable for short delays during lock contention, this could be problematic if the retry delays grow large with exponential backoff.📝 Optional: Add comment about CPU impact
// Fallback: busy-wait loop (less efficient but universally compatible) + // Note: This may cause high CPU usage for longer waits. Consider if this + // becomes an issue with large exponential backoff delays. const end = Date.now() + ms; while (Date.now() < end) { // Busy wait - intentionally empty }
153-165: Lock release warning uses console.warn instead of log utility.Lines 161-163 use
console.warndirectly instead of thelog('warn', ...)utility defined in this file. For consistency with the codebase's logging patterns and silent mode support, consider using the log utility.♻️ Use log utility for consistency
} catch (releaseError) { // Always log lock release failures - they indicate potential issues - console.warn( - `[WARN] Failed to release lock for ${filepath}: ${releaseError.message}` - ); + log('warn', `Failed to release lock for ${filepath}: ${releaseError.message}`); }packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts (1)
236-242: Consider adding a test for lock file cleanup on writeJson.The
writeJsontests verify atomic writes but don't explicitly check for absence of.lockfiles after completion, unlike themodifyJsontests. Consider adding this for consistency.📝 Optional: Add lock file check to writeJson test
it('should not leave temp files on success', async () => { await fileOps.writeJson(testFilePath, { test: true }); const files = await fs.readdir(tempDir); const tempFiles = files.filter((f) => f.includes('.tmp')); expect(tempFiles).toHaveLength(0); + + // Also verify no lock files remain + const lockFiles = files.filter((f) => f.endsWith('.lock')); + expect(lockFiles).toHaveLength(0); });
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (6)
.changeset/fix-file-locking.mdpackages/tm-core/package.jsonpackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.jstests/unit/file-locking.test.js
✅ Files skipped from review due to trivial changes (1)
- .changeset/fix-file-locking.md
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/tm-core/package.json
- tests/unit/file-locking.test.js
🧰 Additional context used
📓 Path-based instructions (13)
scripts/modules/utils.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
When adding utilities to
utils.js, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Files:
scripts/modules/utils.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
**/*.js: Always use isSilentMode() function to check current silent mode status instead of directly accessing the global silentMode variable or global.silentMode
Use try/finally block pattern when wrapping core function calls with enableSilentMode/disableSilentMode to ensure silent mode is always restored, even if errors occur
For functions that need to handle both a passed silentMode parameter and check global state, check both the function parameter and global state: const isSilent = options.silentMode || (typeof options.silentMode === 'undefined' && isSilentMode())
Functions should accept their dependencies as parameters rather than using globals to promote testability and explicit dependency injection
Define callbacks as separate functions for easier testing rather than inline functions
Files:
scripts/modules/utils.js
scripts/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/context_gathering.mdc)
scripts/**/*.js: Use theContextGathererclass fromscripts/modules/utils/contextGatherer.jsto extract context from multiple sources (tasks, files, custom text, project tree) with token counting usinggpt-tokenslibrary
InitializeContextGathererwith project root and tasks path, then callgather()method with tasks array, files array, customContext, includeProjectTree, format ('research', 'chat', or 'system-prompt'), and includeTokenCounts options
Use theFuzzyTaskSearchclass fromscripts/modules/utils/fuzzyTaskSearch.jsfor intelligent task discovery with semantic matching, purpose categorization, and relevance scoring using Fuse.js
Implement a three-step initialization pattern for context-aware commands: (1) validate and parse parameters, (2) initialize context gatherer and find project root, (3) auto-discover relevant tasks using fuzzy search if task IDs not specified
Display token breakdown usingboxenlibrary with sections for tasks, files, and prompts, showing formatted token counts and file sizes in a clean bordered box with title
Process AI result responses usingcli-highlightlibrary to apply syntax highlighting to code blocks with language detection in the formatlanguage\ncode
Set reasonable file size limits (50KB default) and project tree depth limits (3-5 levels) when gathering context to maintain performance
Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior
Files:
scripts/modules/utils.js
scripts/modules/**/*
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
Restart the MCP server if core logic in
scripts/modulesor MCP tool definitions change
Files:
scripts/modules/utils.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/mcp.mdc)
When implementing MCP support for a command, ensure the core logic function can suppress console output via an outputFormat parameter or other mechanism
scripts/modules/*.js: Use consistent file naming conventions:task_${id.toString().padStart(3, '0')}.txtfor task files; usepath.join()for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
UseisSilentMode()function to check global silent mode status; wrap core function calls within direct functions usingenableSilentMode()anddisableSilentMode()in try/finally blocks if the core function produces console output not reliably controlled by outputFormat parameter
Ensure AI calls correctly handle and propagatetelemetryDataas described intelemetry.mdc
Import context gathering utilities (ContextGatherer,FuzzyTaskSearch) for AI-powered commands; support multiple context types (tasks, files, custom text, project tree); implement detailed token breakdown display
PrefergenerateTextServicefor calls sending large context (like stringified JSON) where incremental display is not needed; import necessary service functions fromai-services-unified.jsand prepare parameters (role, session, systemPrompt, prompt)
Create a clear unidirectional flow of dependencies between modules; separate business logic from UI rendering to avoid circular dependencies
Design functions to accept dependencies as parameters; avoid hard-coded dependencies that are difficult to mock
Keep pure logic separate from I/O operations or UI rendering to allow testing logic without mocking complex dependencies
Design core logic to work wi...
Files:
scripts/modules/utils.js
**/*.{js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
JavaScript test files using Jest must follow the same testing patterns as TypeScript files, include proper mocking of external dependencies, and achieve the same coverage thresholds
Files:
scripts/modules/utils.js
**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements
Files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
scripts/modules/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
scripts/modules/**/*.{js,ts}: Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
When a logger object is passed as a parameter to core functions, ensure the receiving function can call methods like .info, .warn, .error on that object
Files:
scripts/modules/utils.js
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Import modules with
.jsextension even in TypeScript source files for ESM compatibility
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
**/*.spec.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Place package and app test files in
packages/<package-name>/src/<module>/<file>.spec.tsorapps/<app-name>/src/<module>/<file>.spec.tsalongside source files
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
**/*.{spec,test}.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{spec,test}.ts: Always use.tsfor TypeScript tests, never.js
NEVER use async/await in test functions unless testing actual asynchronous operations; use synchronous top-level imports instead of dynamicawait import()
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
packages/tm-core/**/*.{spec,test}.ts
📄 CodeRabbit inference engine (CLAUDE.md)
In unit tests for @tm/core, mock only external I/O (Supabase, APIs, filesystem) and use real internal services
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
🧠 Learnings (61)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Place utilities used primarily by the core task-master CLI logic and command modules into scripts/modules/utils.js
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Export all utility functions explicitly in logical groups and include configuration constants from utility modules
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:59:00.056Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/context_gathering.mdc:0-0
Timestamp: 2025-11-24T17:59:00.056Z
Learning: Applies to scripts/modules/utils/{contextGatherer,fuzzyTaskSearch}.js : Export utility modules using named exports: `ContextGatherer`, `createContextGatherer` from contextGatherer.js and `FuzzyTaskSearch`, `PURPOSE_CATEGORIES`, `RELEVANCE_THRESHOLDS` from fuzzyTaskSearch.js
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Design core logic to work with both legacy (flat tasks array) and tagged task data formats; use tag resolution functions (getTasksForTag, setTasksForTag) for task data access; support silent migration during feature usage
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : In MCP direct functions, support explicit tag specification and use tag resolution for task data operations; default to current tag when not specified
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : For file path handling in destructive operations: use path.join() to construct paths, follow naming conventions (e.g., task_001.txt), check file existence before deletion, and handle errors gracefully without string concatenation
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-08-06T21:12:43.715Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-orchestrator.md:1-6
Timestamp: 2025-08-06T21:12:43.715Z
Learning: In the eyaltoledano/claude-task-master repository, agent files are intentionally duplicated between `.claude/agents/` (for internal project use) and `assets/claude/agents/` (as template files for users to copy). This duplication serves different purposes and should be maintained to support both internal development and user distribution needs.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-08-06T21:12:20.981Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-executor.md:1-6
Timestamp: 2025-08-06T21:12:20.981Z
Learning: In the eyaltoledano/claude-task-master repository, agent files in assets/claude/agents/ are intended for distribution to users (for copying), while identical files in .claude/agents/ are for internal project use. This intentional duplication serves different purposes and is not a DRY violation.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/task-manager.js : Data manipulation features (create, read, update, delete tasks) should be placed in `task-manager.js` and follow guidelines in `tasks.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/commands/**/*.{js,ts} : Handle potential ConfigurationError if the .taskmasterconfig file is missing or invalid when accessed via getConfig
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use consistent file naming conventions: `task_${id.toString().padStart(3, '0')}.txt` for task files; use `path.join()` for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks and self-references during cleanup, tracking and reporting changes made during cleanup
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data after destructive operations, handling both direct and indirect references with explanatory console logging
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI within the current tag context (defaulting to "master"), providing clear prompts to guide AI task generation and validating/cleaning up AI-generated tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data, handle both direct and indirect references, and explain what related data is being updated.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Track and report changes made during dependency cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use path.join() instead of string concatenation for file paths, follow established file naming conventions (task_001.txt format), and use path.dirname() and related path utilities for manipulating paths
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys with helpful hints for fallbacks
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-09-03T13:46:00.640Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/auth/oauth-service.ts:20-20
Timestamp: 2025-09-03T13:46:00.640Z
Learning: For Node.js v22 and later, JSON imports should use `with { type: 'json' }` syntax, not `assert { type: 'json' }`. The `assert` syntax was removed in Node.js v22 in favor of the `with` syntax for import attributes. This applies to the eyaltoledano/claude-task-master codebase which uses Node.js v24.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T05:38:17.352Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 943
File: scripts/modules/task-manager/move-task.js:24-24
Timestamp: 2025-07-18T05:38:17.352Z
Learning: In the Claude Task Master system, core task-manager functions are designed with fallback mechanisms for missing projectRoot parameters using the pattern `const projectRoot = providedProjectRoot || findProjectRoot();`. The readJSON and writeJSON functions have default parameters (projectRoot = null, tag = null) and handle missing parameters gracefully. Adding strict validation to these core functions would break the established flexible architecture pattern.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Ensure AI calls correctly handle and propagate `telemetryData` as described in `telemetry.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Use try/catch blocks for all file operations and return null or a default value on failure rather than allowing exceptions to propagate unhandled
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Implement silent migration in readJSON() function to automatically convert legacy tasks.json format ({"tasks": [...]}) to tagged format ({"master": {"tasks": [...]}}) on first use while preserving all existing task data
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys for features that depend on them.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Pass context object `{ projectRoot, tag }` to all core functions that read or write tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Core task functions must accept a context parameter with `{ projectRoot, tag }` properties
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Implement reusable task finding utilities that support both task and subtask lookups and add context to subtask results
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent properties for subtasks (id, title, description, status, dependencies, details) without duplicating parent task properties, maintaining simple numeric IDs unique within the parent task
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Include all required task properties (id, title, description, status, dependencies, priority, details, testStrategy, subtasks) in each task object without adding extra properties outside the standard schema
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to packages/tm-core/**/*.{spec,test}.ts : In unit tests for tm/core, mock only external I/O (Supabase, APIs, filesystem) and use real internal services
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks during cleanup
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Applies to tests/teardown.ts : Global teardown file must be created to handle cleanup after all tests complete and prevent worker process leaks
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Do not leave dangling references after deletion.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use findTasksJsonPath utility within direct functions to locate the tasks.json file consistently
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Mock file system operations using `mock-fs` library. Mock API calls by providing jest.fn() implementations that return expected structures. Mock environment variables in test setup.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Create simplified test functions instead of complex setups: create simplified versions of complex functions focusing on core logic; remove file system operations, API calls, and external dependencies; pass all dependencies as parameters.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to **/tests/integration/**/*.{spec,test}.ts : In integration tests, use real tm-core and mock only external boundaries (APIs, DB, filesystem)
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : When testing CLI commands built with Commander.js: test command action handlers directly rather than mocking the entire Commander chain; create simplified test-specific implementations of command handlers; explicitly handle all options including defaults and shorthand flags; include null/undefined checks for optional parameters; use fixtures for consistent sample data.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to tests/unit/**/*.test.js : Locate unit tests in `tests/unit/` directory. Test individual functions and utilities in isolation, mock all external dependencies, keep tests small and focused.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Never use asynchronous operations in tests. Always mock tests properly based on the way the tested functions are defined and used.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Applies to **/*.test.ts : Unit tests must follow the describe/it pattern, use beforeEach for mock setup with jest.clearAllMocks(), include specific assertions with expect(), and test both success and error scenarios including edge cases
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
🧬 Code graph analysis (2)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (4)
scripts/modules/utils.js (3)
data(579-579)dir(76-76)dir(177-177)scripts/modules/task-manager/update-task-by-id.js (1)
data(120-120)scripts/modules/task-manager/update-subtask-by-id.js (1)
data(123-123)scripts/modules/task-manager/list-tasks.js (1)
data(46-46)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts (1)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (1)
FileOperations(35-288)
⏰ 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). (2)
- GitHub Check: Test
- GitHub Check: Cursor Bugbot
🔇 Additional comments (22)
scripts/modules/utils.js (8)
22-27: LGTM - Lock configuration looks appropriate.The 10-second stale lock timeout and exponential backoff retry strategy are reasonable defaults for cross-process coordination.
103-145: Well-designed stale lock handling with atomic rename.The approach of using atomic rename to safely take ownership of stale locks (lines 112-126) correctly prevents race conditions where two processes might try to clean up the same stale lock simultaneously. The exponential backoff on retries is also well implemented.
175-269: Sync implementation mirrors async correctly.The
withFileLockSyncimplementation correctly parallelswithFileLockwith synchronous equivalents. The stale lock detection and atomic rename pattern are properly replicated.Same note about
console.warnat lines 264-266 - consider usinglog('warn', ...)for consistency.
965-1012: Re-reading file inside lock is the correct pattern for preventing lost updates.The logic at lines 971-1011 properly handles the edge case where
_rawTaggedDatais missing but we have resolved tag data. Re-reading the file inside the lock (lines 989-998) ensures we get the current state, which is essential for preventing lost updates in concurrent scenarios.
1015-1046: Good: Re-reading file inside lock for _rawTaggedData path.Lines 1020-1031 correctly re-read the file inside the lock instead of using potentially stale
_rawTaggedData. This addresses the core race condition where multiple processes could have stale snapshots.
1093-1109: Atomic write pattern is correctly implemented.The temp-file + rename approach (lines 1095-1108) is the standard pattern for atomic file writes. The cleanup of temp files on failure is handled correctly.
1115-1122: Good: Error is now re-thrown after logging.Lines 1120-1121 correctly re-throw the error after logging, ensuring callers are notified of write failures. This is important for error propagation in the locking scenario.
1925-1927: New exports are properly added.The new locking utilities (
withFileLock,withFileLockSync) andnormalizeTaskIdsare correctly exported for use by other modules.packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (6)
18-27: Lock configuration is consistent with utils.js.The 10-second stale timeout and retry configuration align with the JavaScript implementation. Using
realpath: falseis a reasonable optimization.
36-49: Writer caching is a good optimization.Caching steno Writers per file path avoids repeatedly creating new instances and improves performance for frequent writes to the same file.
69-106: writeJson warning comment should be heeded by callers.Lines 72-73 correctly warn that
writeJsonreplaces the entire file and thatmodifyJsonshould be used for concurrent modifications. This is an important API contract.The lock release error handling at lines 92-104 appropriately logs warnings without throwing, which is correct since the write already succeeded.
129-155: Robust error handling for file read inside lock.The error handling distinguishes between:
- ENOENT (file doesn't exist) - starts fresh
- Empty/whitespace files - starts fresh
- Actual JSON corruption - throws descriptive error
- Other I/O errors - surfaces appropriately
This comprehensive handling prevents silent data loss while allowing legitimate empty-file scenarios.
140-141: Edge case: Whitespace-only content not explicitly handled.Line 141 checks for empty string or
'{}', but a file containing only whitespace (e.g.,' \n ') would fail thecontent.trim() === ''check if trim results in empty string. Actually, looking closer,' \n '.trim() === ''is true, so this is handled correctly.
277-287: Cleanup correctly clears writer cache.The comment at lines 284-285 is accurate - steno Writers manage their own file descriptor cleanup. Clearing the Map allows garbage collection.
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts (8)
18-31: Good test isolation with per-test temp directories.Each test gets its own temp directory and FileOperations instance, ensuring proper isolation. The cleanup in afterEach is thorough.
75-91: Test verifies the core re-read-inside-lock behavior.This test at lines 75-91 validates that sequential modifications both apply correctly because the file is re-read inside the lock. This is the critical behavior for preventing lost updates.
93-105: Good: Verifies no lock file artifacts remain.Testing for absence of
.lockfiles after successful operations ensures proper cleanup.
107-121: Critical test: Lock release on modifier error.This test verifies that if the modifier throws, the lock is still released and subsequent operations can proceed. This prevents deadlocks from error conditions.
142-149: Good coverage for corrupted JSON detection.The test at lines 142-149 ensures that actual corrupted JSON (not just empty) throws an appropriate error with a descriptive message.
179-199: Concurrent modification test validates serialization.The test spawns 5 concurrent
modifyJsoncalls and verifies the final count equals 5, proving that modifications are properly serialized and no updates are lost.
201-223: Multi-instance concurrency test is valuable.Testing concurrent writes from multiple FileOperations instances validates the cross-process locking behavior (since each instance simulates a separate process context within proper-lockfile's scope).
245-259: Cleanup test verifies writers can be recreated.The test confirms that after cleanup, the FileOperations instance remains functional by creating new writers as needed. This is important for long-running processes that may need to release resources periodically.
7ed83e6 to
1135f36
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @scripts/modules/utils.js:
- Around line 982-1132: The Biome formatter is flagging formatting issues in the
writeJSON block inside the withFileLockSync callback; run the Biome formatter
(e.g., biome format <file> or the project-wide formatter) and commit the changes
so the spacing/indentation and punctuation in the withFileLockSync callback, the
conditional blocks that reference getCurrentTag/projectRoot/data._rawTaggedData,
and the atomic write sequence using tempPath are normalized; ensure you format
the file containing writeJSON and withFileLockSync (no functional changes) and
then re-run CI.
- Around line 170-175: Formatting errors in scripts/modules/utils.js (notably
around the catch block handling releaseError and also around lines 281-286) are
failing CI; run the formatter and commit the changes. Execute the project
formatter (npm run format-check -- --write or biome format .) to automatically
fix whitespace/semicolon/indentation issues in the catch block that logs
releaseError and in the other affected block, then stage and commit the updated
files so CI passes.
In @tests/unit/file-locking.test.js:
- Around line 95-104: The test file has Biome formatting issues around the
'should create file if createIfMissing is true' test; run the formatter and
commit the changes: run npm run format-check -- --write (or your project's
format script) on tests/unit/file-locking.test.js, then ensure consistent
indentation and spacing around the test block that uses
withFileLockSync(newFilePath, ..., { createIfMissing: true }), and re-run the
linter/CI to confirm formatting is fixed before pushing.
🧹 Nitpick comments (2)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (1)
133-155: Consider trimming content before checking for empty file.The logic checks
content.trim() === ''but the priorfs.readFilecall could fail if the file was deleted between the first and second read. Also, the content substring truncation at line 146 could cut mid-character for UTF-8.🔧 Suggested improvement
} catch (err: any) { // Distinguish between expected empty/new files and actual corruption if (err.code === 'ENOENT') { // File doesn't exist yet - start fresh currentData = {} as T; } else if (err instanceof SyntaxError) { // Check if it's just an empty file (our ensureFileExists writes '{}') - const content = await fs.readFile(filePath, 'utf-8').catch(() => ''); + let content = ''; + try { + content = await fs.readFile(filePath, 'utf-8'); + } catch { + // File was deleted between reads - treat as empty + currentData = {} as T; + continue; // Would need restructuring to use this + } if (content.trim() === '' || content.trim() === '{}') { currentData = {} as T; } else {The current approach with
.catch(() => '')is acceptable since an empty string will match thecontent.trim() === ''condition, but the flow could be clearer.scripts/modules/utils.js (1)
40-65: Busy-wait fallback may cause high CPU usage with exponential backoff.The comment at line 59-60 acknowledges this, but with exponential backoff the maximum wait is
100 * 2^4 = 1600ms, which could cause noticeable CPU consumption. Consider adding a warning or documenting this limitation more prominently.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.tsscripts/modules/utils.jstests/unit/file-locking.test.js
🧰 Additional context used
📓 Path-based instructions (17)
scripts/modules/utils.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
When adding utilities to
utils.js, only add functions that could be used by multiple modules; keep utilities single-purpose and purely functional; document parameters and return values
Files:
scripts/modules/utils.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
**/*.js: Always use isSilentMode() function to check current silent mode status instead of directly accessing the global silentMode variable or global.silentMode
Use try/finally block pattern when wrapping core function calls with enableSilentMode/disableSilentMode to ensure silent mode is always restored, even if errors occur
For functions that need to handle both a passed silentMode parameter and check global state, check both the function parameter and global state: const isSilent = options.silentMode || (typeof options.silentMode === 'undefined' && isSilentMode())
Functions should accept their dependencies as parameters rather than using globals to promote testability and explicit dependency injection
Define callbacks as separate functions for easier testing rather than inline functions
Files:
scripts/modules/utils.jstests/unit/file-locking.test.js
scripts/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/context_gathering.mdc)
scripts/**/*.js: Use theContextGathererclass fromscripts/modules/utils/contextGatherer.jsto extract context from multiple sources (tasks, files, custom text, project tree) with token counting usinggpt-tokenslibrary
InitializeContextGathererwith project root and tasks path, then callgather()method with tasks array, files array, customContext, includeProjectTree, format ('research', 'chat', or 'system-prompt'), and includeTokenCounts options
Use theFuzzyTaskSearchclass fromscripts/modules/utils/fuzzyTaskSearch.jsfor intelligent task discovery with semantic matching, purpose categorization, and relevance scoring using Fuse.js
Implement a three-step initialization pattern for context-aware commands: (1) validate and parse parameters, (2) initialize context gatherer and find project root, (3) auto-discover relevant tasks using fuzzy search if task IDs not specified
Display token breakdown usingboxenlibrary with sections for tasks, files, and prompts, showing formatted token counts and file sizes in a clean bordered box with title
Process AI result responses usingcli-highlightlibrary to apply syntax highlighting to code blocks with language detection in the formatlanguage\ncode
Set reasonable file size limits (50KB default) and project tree depth limits (3-5 levels) when gathering context to maintain performance
Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior
Files:
scripts/modules/utils.js
scripts/modules/**/*
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
Restart the MCP server if core logic in
scripts/modulesor MCP tool definitions change
Files:
scripts/modules/utils.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/mcp.mdc)
When implementing MCP support for a command, ensure the core logic function can suppress console output via an outputFormat parameter or other mechanism
scripts/modules/*.js: Use consistent file naming conventions:task_${id.toString().padStart(3, '0')}.txtfor task files; usepath.join()for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
UseisSilentMode()function to check global silent mode status; wrap core function calls within direct functions usingenableSilentMode()anddisableSilentMode()in try/finally blocks if the core function produces console output not reliably controlled by outputFormat parameter
Ensure AI calls correctly handle and propagatetelemetryDataas described intelemetry.mdc
Import context gathering utilities (ContextGatherer,FuzzyTaskSearch) for AI-powered commands; support multiple context types (tasks, files, custom text, project tree); implement detailed token breakdown display
PrefergenerateTextServicefor calls sending large context (like stringified JSON) where incremental display is not needed; import necessary service functions fromai-services-unified.jsand prepare parameters (role, session, systemPrompt, prompt)
Create a clear unidirectional flow of dependencies between modules; separate business logic from UI rendering to avoid circular dependencies
Design functions to accept dependencies as parameters; avoid hard-coded dependencies that are difficult to mock
Keep pure logic separate from I/O operations or UI rendering to allow testing logic without mocking complex dependencies
Design core logic to work wi...
Files:
scripts/modules/utils.js
**/*.{js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
JavaScript test files using Jest must follow the same testing patterns as TypeScript files, include proper mocking of external dependencies, and achieve the same coverage thresholds
Files:
scripts/modules/utils.jstests/unit/file-locking.test.js
**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements
Files:
scripts/modules/utils.jstests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
scripts/modules/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
scripts/modules/**/*.{js,ts}: Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
When a logger object is passed as a parameter to core functions, ensure the receiving function can call methods like .info, .warn, .error on that object
Files:
scripts/modules/utils.js
tests/unit/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
Unit tests should be located in tests/unit/ and reflect the module structure with one test file per module
Files:
tests/unit/file-locking.test.js
**/*.test.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/new_features.mdc)
**/*.test.{js,ts}: Follow the mock-first-then-import pattern for Jest mocking; use jest.spyOn() for spy functions; clear mocks between tests; verify mocks with the pattern described intests.mdc
Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Files:
tests/unit/file-locking.test.js
**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
**/*.test.js: Never use asynchronous operations in tests. Always mock tests properly based on the way the tested functions are defined and used.
Follow Jest test file structure: 1) Imports, 2) Mock setup before importing modules under test, 3) Import modules after mocks, 4) Set up spies on mocked modules, 5) Describe suite with descriptive name, 6) Setup/teardown hooks, 7) Grouped tests for related functionality, 8) Individual test cases with clear descriptions using Arrange-Act-Assert pattern.
When testing CLI commands built with Commander.js: test command action handlers directly rather than mocking the entire Commander chain; create simplified test-specific implementations of command handlers; explicitly handle all options including defaults and shorthand flags; include null/undefined checks for optional parameters; use fixtures for consistent sample data.
Usejest.mock()before any imports. Jest hoists mock calls to the top of the file. Always declare mocks before importing modules being tested. Use factory pattern for complex mocks that need access to other variables.
When testing ES modules with dynamic imports, usejest.unstable_mockModule()beforeawait import(). Include__esModule: truein mock factories. Reset mock functions before dynamic import. Mock named and default exports as needed.
Mock file system operations usingmock-fslibrary. Mock API calls by providing jest.fn() implementations that return expected structures. Mock environment variables in test setup.
When testing functions with callbacks: get the callback from mock's call arguments usingmock.calls[index][argIndex]; execute it directly with test inputs; verify results match expectations.
For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mockreadJSONandwriteJSONto avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed t...
Files:
tests/unit/file-locking.test.js
tests/unit/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
Locate unit tests in
tests/unit/directory. Test individual functions and utilities in isolation, mock all external dependencies, keep tests small and focused.
Files:
tests/unit/file-locking.test.js
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
**/*.spec.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Place package and app test files in
packages/<package-name>/src/<module>/<file>.spec.tsorapps/<app-name>/src/<module>/<file>.spec.tsalongside source files
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
**/*.{spec,test}.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{spec,test}.ts: Always use.tsfor TypeScript tests, never.js
NEVER use async/await in test functions unless testing actual asynchronous operations; use synchronous top-level imports instead of dynamicawait import()
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Import modules with
.jsextension even in TypeScript source files for ESM compatibility
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
packages/tm-core/**/*.{spec,test}.ts
📄 CodeRabbit inference engine (CLAUDE.md)
In unit tests for @tm/core, mock only external I/O (Supabase, APIs, filesystem) and use real internal services
Files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
🧠 Learnings (63)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1444
File: apps/cli/src/utils/auto-update/changelog.ts:103-111
Timestamp: 2025-11-25T18:32:29.828Z
Learning: The claude-task-master project uses a custom changelog format with PR numbers and author acknowledgements in the pattern `- [#PR](...) Thanks [author]! - Description`, which is parsed by the regex in apps/cli/src/utils/auto-update/changelog.ts.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/utils.js : utils.js should provide core utility functions including logging (log function), file I/O (readJSON, writeJSON), string utilities (truncate), task utilities (findTaskById), dependency utilities (findCycles), API key resolution (resolveEnvVariable), silent mode control (enableSilentMode, disableSilentMode), and tagged task list support (migration system, tag resolution, current tag management)
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently; minimize file I/O operations per feature execution; cache tag resolution results when appropriate; avoid keeping all tag data in memory simultaneously
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Place utilities used primarily by the core task-master CLI logic and command modules into scripts/modules/utils.js
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Use `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)` for all task data access
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Format task files with consistent structure including task metadata (ID, title, status), dependencies with status indicators, and tag context information in the file header
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.js
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
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:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Export all utility functions explicitly in logical groups and include configuration constants from utility modules
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Make async operations synchronous in tests. Mock async functions to return synchronous values when possible. Don't use real async/await or Promise resolution that might fail unpredictably.
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Use path.join() to construct file paths, follow established naming conventions (like task_001.txt), check file existence before deletion, and handle file deletion errors gracefully.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : For task file operations in tests: use test-specific file paths (e.g., 'test-tasks.json'); mock `readJSON` and `writeJSON` to avoid real file system interactions; verify file operations use correct paths; use different paths for each test; verify modifications on in-memory task objects passed to `writeJSON`.
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to **/*.test.{js,ts} : Test new features with both legacy and tagged task data formats; verify tag resolution behavior; test migration compatibility; ensure pre-migration projects are handled correctly
Applied to files:
scripts/modules/utils.jstests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Design core logic to work with both legacy (flat tasks array) and tagged task data formats; use tag resolution functions (getTasksForTag, setTasksForTag) for task data access; support silent migration during feature usage
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : In MCP direct functions, support explicit tag specification and use tag resolution for task data operations; default to current tag when not specified
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : For file path handling in destructive operations: use path.join() to construct paths, follow naming conventions (e.g., task_001.txt), check file existence before deletion, and handle errors gracefully without string concatenation
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-08-06T21:12:43.715Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-orchestrator.md:1-6
Timestamp: 2025-08-06T21:12:43.715Z
Learning: In the eyaltoledano/claude-task-master repository, agent files are intentionally duplicated between `.claude/agents/` (for internal project use) and `assets/claude/agents/` (as template files for users to copy). This duplication serves different purposes and should be maintained to support both internal development and user distribution needs.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-08-06T21:12:20.981Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1091
File: assets/claude/agents/task-executor.md:1-6
Timestamp: 2025-08-06T21:12:20.981Z
Learning: In the eyaltoledano/claude-task-master repository, agent files in assets/claude/agents/ are intended for distribution to users (for copying), while identical files in .claude/agents/ are for internal project use. This intentional duplication serves different purposes and is not a DRY violation.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/task-manager.js : Data manipulation features (create, read, update, delete tasks) should be placed in `task-manager.js` and follow guidelines in `tasks.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 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:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/commands/**/*.{js,ts} : Handle potential ConfigurationError if the .taskmasterconfig file is missing or invalid when accessed via getConfig
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Use consistent file naming conventions: `task_${id.toString().padStart(3, '0')}.txt` for task files; use `path.join()` for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use path.join() instead of string concatenation for file paths, follow established file naming conventions (task_001.txt format), and use path.dirname() and related path utilities for manipulating paths
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks and self-references during cleanup, tracking and reporting changes made during cleanup
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data after destructive operations, handling both direct and indirect references with explanatory console logging
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI within the current tag context (defaulting to "master"), providing clear prompts to guide AI task generation and validating/cleaning up AI-generated tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Clean up references to deleted items in other parts of the data, handle both direct and indirect references, and explain what related data is being updated.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/**/*.{js,ts} : Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Track and report changes made during dependency cleanup
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-09-03T13:46:00.640Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/auth/oauth-service.ts:20-20
Timestamp: 2025-09-03T13:46:00.640Z
Learning: For Node.js v22 and later, JSON imports should use `with { type: 'json' }` syntax, not `assert { type: 'json' }`. The `assert` syntax was removed in Node.js v22 in favor of the `with` syntax for import attributes. This applies to the eyaltoledano/claude-task-master codebase which uses Node.js v24.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-07-18T05:38:17.352Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 943
File: scripts/modules/task-manager/move-task.js:24-24
Timestamp: 2025-07-18T05:38:17.352Z
Learning: In the Claude Task Master system, core task-manager functions are designed with fallback mechanisms for missing projectRoot parameters using the pattern `const projectRoot = providedProjectRoot || findProjectRoot();`. The readJSON and writeJSON functions have default parameters (projectRoot = null, tag = null) and handle missing parameters gracefully. Adding strict validation to these core functions would break the established flexible architecture pattern.
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/*.js : Ensure AI calls correctly handle and propagate `telemetryData` as described in `telemetry.mdc`
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Use try/catch blocks for all file operations and return null or a default value on failure rather than allowing exceptions to propagate unhandled
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Include error handling for JSON file operations and validate JSON structure after reading
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Implement silent migration in readJSON() function to automatically convert legacy tasks.json format ({"tasks": [...]}) to tagged format ({"master": {"tasks": [...]}}) on first use while preserving all existing task data
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys with helpful hints for fallbacks
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys for features that depend on them.
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Pass context object `{ projectRoot, tag }` to all core functions that read or write tasks
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:04.644Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tags.mdc:0-0
Timestamp: 2025-11-24T18:02:04.644Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,mjs} : Core task functions must accept a context parameter with `{ projectRoot, tag }` properties
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Applied to files:
scripts/modules/utils.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-12-11T14:45:14.973Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/AGENTS.md:0-0
Timestamp: 2025-12-11T14:45:14.973Z
Learning: Applies to assets/.taskmaster/tasks/tasks.json : Store main task data in `.taskmaster/tasks/tasks.json` and never manually edit this file - use Task Master commands instead
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Implement reusable task finding utilities that support both task and subtask lookups and add context to subtask results
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent properties for subtasks (id, title, description, status, dependencies, details) without duplicating parent task properties, maintaining simple numeric IDs unique within the parent task
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Include all required task properties (id, title, description, status, dependencies, priority, details, testStrategy, subtasks) in each task object without adding extra properties outside the standard schema
Applied to files:
scripts/modules/utils.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to tests/unit/**/*.test.js : Locate unit tests in `tests/unit/` directory. Test individual functions and utilities in isolation, mock all external dependencies, keep tests small and focused.
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Create simplified test functions instead of complex setups: create simplified versions of complex functions focusing on core logic; remove file system operations, API calls, and external dependencies; pass all dependencies as parameters.
Applied to files:
tests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Applies to tests/teardown.ts : Global teardown file must be created to handle cleanup after all tests complete and prevent worker process leaks
Applied to files:
tests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.tspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : When testing CLI commands built with Commander.js: test command action handlers directly rather than mocking the entire Commander chain; create simplified test-specific implementations of command handlers; explicitly handle all options including defaults and shorthand flags; include null/undefined checks for optional parameters; use fixtures for consistent sample data.
Applied to files:
tests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Never use asynchronous operations in tests. Always mock tests properly based on the way the tested functions are defined and used.
Applied to files:
tests/unit/file-locking.test.jspackages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Detect circular dependencies using DFS and validate task references before operations
Applied to files:
tests/unit/file-locking.test.js
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to packages/tm-core/**/*.{spec,test}.ts : In unit tests for tm/core, mock only external I/O (Supabase, APIs, filesystem) and use real internal services
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:03:46.713Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-11-24T18:03:46.713Z
Learning: Applies to **/*.test.js : Mock file system operations using `mock-fs` library. Mock API calls by providing jest.fn() implementations that return expected structures. Mock environment variables in test setup.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to **/tests/integration/**/*.{spec,test}.ts : In integration tests, use real tm-core and mock only external boundaries (APIs, DB, filesystem)
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Applies to **/*.integration.test.ts : Integration tests must use supertest for API endpoint testing, verify database state changes after operations, clean test data before each test, and include full request/response validation with expected HTTP status codes
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:03:13.456Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-11-24T18:03:13.456Z
Learning: Applies to **/*.test.ts : Unit tests must follow the describe/it pattern, use beforeEach for mock setup with jest.clearAllMocks(), include specific assertions with expect(), and test both success and error scenarios including edge cases
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/*.{js,ts} : Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for and remove references to non-existent tasks during cleanup
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Do not leave dangling references after deletion.
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
📚 Learning: 2025-11-24T18:01:06.077Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-11-24T18:01:06.077Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Use findTasksJsonPath utility within direct functions to locate the tasks.json file consistently
Applied to files:
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts
🧬 Code graph analysis (3)
scripts/modules/utils.js (9)
scripts/modules/task-manager/move-task.js (2)
options(118-118)options(700-700)scripts/modules/sync-readme.js (1)
options(53-53)mcp-server/src/core/direct-functions/initialize-project.js (1)
options(67-73)scripts/modules/task-manager/expand-task.js (2)
data(97-97)projectRoot(64-64)scripts/modules/task-manager/update-task-by-id.js (2)
data(120-120)projectRoot(77-77)scripts/modules/task-manager/update-tasks.js (2)
data(75-75)projectRoot(69-69)scripts/modules/task-manager/expand-all-tasks.js (2)
data(86-86)projectRoot(47-47)src/utils/path-utils.js (2)
projectRoot(77-77)tag(351-351)mcp-server/src/tools/utils.js (1)
projectRoot(247-249)
tests/unit/file-locking.test.js (2)
scripts/modules/utils.js (4)
result(769-773)data(596-596)lockPath(99-99)lockPath(210-210)tests/unit/task-manager/tag-management.test.js (1)
initialData(18-26)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts (1)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (1)
FileOperations(35-288)
🪛 GitHub Actions: CI
scripts/modules/utils.js
[error] 170-175: Biome format-check would reformat code in this file. Run 'biome format .' or 'npm run format-check -- --write' to fix formatting.
[error] 281-289: Biome format-check would reformat code in this file. Run 'biome format .' or 'npm run format-check -- --write' to fix formatting.
[error] 983-991: Biome format-check would reformat code in this file. Run 'biome format .' or 'npm run format-check -- --write' to fix formatting.
tests/unit/file-locking.test.js
[error] 96-104: Biome format-check would reformat code in this file. Run 'biome format .' or 'npm run format-check -- --write' to fix formatting.
⏰ 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: Cursor Bugbot
🔇 Additional comments (18)
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts (4)
15-27: LGTM! Reasonable lock configuration.The lock options are well-tuned: 10-second stale timeout catches crashed processes, exponential backoff (100ms-1000ms) with 5 retries balances responsiveness with contention handling, and
realpath: falseavoids unnecessary syscalls.
36-49: LGTM! Writer caching promotes efficiency.Caching
stenoWriters per file path avoids repeated Writer instantiation overhead for files that are written multiple times during a session.
181-197: LGTM! Atomic file creation with TOCTOU prevention.Using the
'wx'flag for exclusive creation is the correct approach to prevent race conditions between checking file existence and creating it.
277-287: LGTM! Cleanup implementation is appropriate.The comment correctly notes that steno Writers don't need explicit close calls—clearing the map allows garbage collection.
scripts/modules/utils.js (3)
22-27: LGTM! Lock configuration aligns with TypeScript implementation.The 10-second stale timeout matches the
LOCK_OPTIONS.staleinfile-operations.ts, ensuring consistent cross-process behavior between JS and TS code paths.
119-137: LGTM! Stale lock recovery uses atomic rename for safety.The pattern of renaming the stale lock to a unique path before deleting prevents accidentally removing another process's freshly-acquired lock. This is a correct approach to handle stale locks safely.
1111-1127: LGTM! Atomic write with temp-file and rename.The temp-file + rename pattern ensures the original file is never left in a partial state. The cleanup in the catch block prevents leftover temp files on failure.
tests/unit/file-locking.test.js (4)
1-17: LGTM! Well-structured test setup with proper isolation.The test file correctly imports Jest globals and sets up file path resolution for ESM compatibility.
218-238: LGTM! Concurrent write serialization test.This test validates that multiple concurrent writes via
Promise.allare properly serialized by the locking mechanism, resulting in deterministic final state.
341-504: LGTM! Excellent multi-process concurrency test.The worker script with inline locking implementation provides a realistic cross-process concurrency scenario. The 30-second timeout is appropriate for this heavyweight test.
One consideration: the test relies on all processes completing successfully. If a process hangs due to a deadlock, the test would timeout rather than provide a specific failure message. This is acceptable for catching race conditions.
574-593: LGTM! Stale lock detection test.The test correctly validates that stale locks (older than the configured threshold) are removed to allow lock acquisition, preventing indefinite blocking from crashed processes.
packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.spec.ts (7)
6-11: LGTM! Correct use of Vitest for TypeScript package testing.The imports use Vitest (not Jest), which aligns with the project's TypeScript testing infrastructure in
tm-core.
25-31: LGTM! Proper cleanup in afterEach.The test correctly calls
fileOps.cleanup()before removing the temp directory, ensuring cached Writers are released before filesystem cleanup.
75-91: LGTM! Test validates re-read-inside-lock behavior.This test confirms that sequential
modifyJsoncalls each read the current file state inside the lock, preventing lost updates from stale data.
123-140: LGTM! Edge case coverage for empty and whitespace-only files.These tests validate the graceful handling of empty files and files with only whitespace, ensuring they're treated as fresh/empty rather than corrupted.
142-149: LGTM! Corrupted JSON detection test.Validates that actual corrupted JSON (not just empty/whitespace) throws an appropriate error message, helping users identify data corruption issues.
179-223: LGTM! Concurrent operation tests validate serialization.Both tests (single instance and multiple instances) verify that concurrent
modifyJsoncalls are properly serialized, with the final count matching the number of concurrent operations. This is the core correctness guarantee for the locking mechanism.
249-263: LGTM! Cleanup behavior test.Validates that
cleanup()clears internal state while allowing continued use of the instance with fresh Writers.
- **writeJSON now propagates errors**: Previously swallowed all errors silently,
making it impossible for callers to detect write failures. Now re-throws after
logging so callers can handle failures appropriately.
- **modifyJson distinguishes corruption from empty files**: Instead of silently
replacing corrupted JSON with `{}`, now:
- ENOENT (file not found) → Start fresh with `{}`
- Empty/whitespace files → Start fresh with `{}`
- Actual corrupted JSON → Throws descriptive error with file content preview
- **Lock release failures now logged**: Changed from silent catch blocks to
`console.warn` so lock release issues are visible for debugging.
- **Debug logging for lock operations**: Added TASKMASTER_DEBUG support for
detailed lock acquisition/release logging.
- Added JSDoc noting cleanup() should be called for long-lived FileOperations
instances to prevent memory leaks from cached Writers.
- Added sleepSync helper with Atomics.wait + busy-wait fallback for environments
without SharedArrayBuffer support.
- Added comprehensive tests for async `withFileLock` function (was untested)
- Added concurrent operation tests for FileOperations class
- Added true multi-process concurrent write test with inline locking
- Tests verify lock serialization, error propagation, and cleanup
1135f36 to
0b05a35
Compare
Refactor file-storage.ts methods to use modifyJson instead of separate readJson/writeJson calls. This ensures the file is re-read inside the cross-process lock, preventing lost updates from stale snapshots. Methods updated: - saveTasks: Now uses modifyJson for atomic updates - createTag: Now uses modifyJson for atomic creation - deleteTag: Now uses modifyJson for legacy format deletion - renameTag: Now uses modifyJson for atomic renaming This complements the cross-process file locking from PR eyaltoledano#1566. Resolves issue eyaltoledano#1568.
Summary
Fixes #1567
This PR addresses a race condition where multiple Claude Code windows (separate processes) accessing Task Master simultaneously could corrupt the JSON file or cause saved work to be lost.
Changes Made
File Locking
withFileLock(async) andwithFileLockSync(sync) utilities for cross-process file lockingproper-lockfilefor async operations with configurable retries and stale detectionwxflag for sync operationsAtomic Writes
Safety Features
wxflag)Atomics.wait()for proper blocking sleepBug Fixes (discovered during review)
createdtimestampTest Plan
tests/unit/file-locking.test.js)Note
Strengthens file write safety across processes to avoid lost updates and partial writes.
withFileLock/withFileLockSyncinscripts/modules/utils.jswith retries, stale-lock cleanup (10s), and atomic temp-file + rename; exported for reuseFileOperationsto useproper-lockfile+stenofor atomic writes; addsmodifyJsonthat re-reads inside the lock,ensureFileExists(atomic create withwx), writer caching, andcleanupFileOperationsand Jest suite simulating concurrent/multi-process writes; verifies serialization and no leftover lock/temp filesproper-lockfileand@types/proper-lockfile; updates package metadata and adds a changeset entryWritten by Cursor Bugbot for commit 0b05a35. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
Bug Fixes
New Features
Tests
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.