feat(paths): Implement robust project root detection and path utilities

Overhauls the project root detection system with a hierarchical precedence mechanism that intelligently locates tasks.json and identifies project roots. This improves user experience by reducing the need for explicit path parameters and enhances cross-platform compatibility.

Key Improvements:
- Implement hierarchical precedence for project root detection:
  * Environment variable override (TASK_MASTER_PROJECT_ROOT)
  * Explicitly provided --project-root parameter
  * Cached project root from previous successful operations
  * Current directory with project markers
  * Parent directory traversal to find tasks.json
  * Package directory as fallback

- Create comprehensive PROJECT_MARKERS detection system with 20+ common indicators:
  * Task Master specific files (tasks.json, tasks/tasks.json)
  * Version control directories (.git, .svn)
  * Package manifests (package.json, pyproject.toml, Gemfile, go.mod, Cargo.toml)
  * IDE/editor configurations (.cursor, .vscode, .idea)
  * Dependency directories (node_modules, venv, .venv)
  * Configuration files (.env, tsconfig.json, webpack.config.js)
  * CI/CD files (.github/workflows, .gitlab-ci.yml, .circleci/config.yml)

- DRY refactoring of path utilities:
  * Centralize path-related functions in core/utils/path-utils.js
  * Export PROJECT_MARKERS as a single source of truth
  * Add caching via lastFoundProjectRoot for performance optimization

- Enhanced user experience:
  * Improve error messages with specific troubleshooting guidance
  * Add detailed logging to indicate project root detection source
  * Update tool parameter descriptions for better clarity
  * Add recursive parent directory searching for tasks.json

Testing:
- Verified in local dev environment
- Added unit tests for the progress bar visualization
- Updated "automatically detected" description in MCP tools

This commit addresses Task #38: Implement robust project root handling for file paths.
This commit is contained in:
Eyal Toledano
2025-04-01 01:35:10 -04:00
parent b23d5afd66
commit e607c5481c
10 changed files with 597 additions and 210 deletions

View File

@@ -923,7 +923,7 @@ Following MCP implementation standards:
8. Update tests to reflect the new naming conventions
9. Create a linting rule to enforce naming conventions in future development
## 34. Review functionality of all MCP direct functions [pending]
## 34. Review functionality of all MCP direct functions [in-progress]
### Dependencies: None
### Description: Verify that all implemented MCP direct functions work correctly with edge cases
### Details:
@@ -947,12 +947,159 @@ Implement the addResearch function in the MCP server's index.js file to enable r
### Details:
Implement the addTemplates function in the MCP server's index.js file to enable template-based generation. Configure proper loading of templates from the appropriate directory and ensure they're accessible to all MCP tools that need to generate formatted content.
## 38. Implement robust project root handling for file paths [pending]
## 38. Implement robust project root handling for file paths [in-progress]
### Dependencies: None
### Description: Create a consistent approach for handling project root paths across MCP tools
### Details:
Analyze and refactor the project root handling mechanism to ensure consistent file path resolution across all MCP direct functions. This should properly handle relative and absolute paths, respect the projectRoot parameter when provided, and have appropriate fallbacks when not specified. Document the approach in a comment within path-utils.js for future maintainers.
<info added on 2025-04-01T02:21:57.137Z>
Here's additional information addressing the request for research on npm package path handling:
## Path Handling Best Practices for npm Packages
### Distinguishing Package and Project Paths
1. **Package Installation Path**:
- Use `require.resolve()` to find paths relative to your package
- For global installs, use `process.execPath` to locate the Node.js executable
2. **Project Path**:
- Use `process.cwd()` as a starting point
- Search upwards for `package.json` or `.git` to find project root
- Consider using packages like `find-up` or `pkg-dir` for robust root detection
### Standard Approaches
1. **Detecting Project Root**:
- Recursive search for `package.json` or `.git` directory
- Use `path.resolve()` to handle relative paths
- Fall back to `process.cwd()` if no root markers found
2. **Accessing Package Files**:
- Use `__dirname` for paths relative to current script
- For files in `node_modules`, use `require.resolve('package-name/path/to/file')`
3. **Separating Package and Project Files**:
- Store package-specific files in a dedicated directory (e.g., `.task-master`)
- Use environment variables to override default paths
### Cross-Platform Compatibility
1. Use `path.join()` and `path.resolve()` for cross-platform path handling
2. Avoid hardcoded forward/backslashes in paths
3. Use `os.homedir()` for user home directory references
### Best Practices for Path Resolution
1. **Absolute vs Relative Paths**:
- Always convert relative paths to absolute using `path.resolve()`
- Use `path.isAbsolute()` to check if a path is already absolute
2. **Handling Different Installation Scenarios**:
- Local dev: Use `process.cwd()` as fallback project root
- Local dependency: Resolve paths relative to consuming project
- Global install: Use `process.execPath` to locate global `node_modules`
3. **Configuration Options**:
- Allow users to specify custom project root via CLI option or config file
- Implement a clear precedence order for path resolution (e.g., CLI option > config file > auto-detection)
4. **Error Handling**:
- Provide clear error messages when critical paths cannot be resolved
- Implement retry logic with alternative methods if primary path detection fails
5. **Documentation**:
- Clearly document path handling behavior in README and inline comments
- Provide examples for common scenarios and edge cases
By implementing these practices, the MCP tools can achieve consistent and robust path handling across various npm installation and usage scenarios.
</info added on 2025-04-01T02:21:57.137Z>
<info added on 2025-04-01T02:25:01.463Z>
Here's additional information addressing the request for clarification on path handling challenges for npm packages:
## Advanced Path Handling Challenges and Solutions
### Challenges to Avoid
1. **Relying solely on process.cwd()**:
- Global installs: process.cwd() could be any directory
- Local installs as dependency: points to parent project's root
- Users may run commands from subdirectories
2. **Dual Path Requirements**:
- Package Path: Where task-master code is installed
- Project Path: Where user's tasks.json resides
3. **Specific Edge Cases**:
- Non-project directory execution
- Deeply nested project structures
- Yarn/pnpm workspaces
- Monorepos with multiple tasks.json files
- Commands invoked from scripts in different directories
### Advanced Solutions
1. **Project Marker Detection**:
- Implement recursive search for package.json or .git
- Use `find-up` package for efficient directory traversal
```javascript
const findUp = require('find-up');
const projectRoot = await findUp(dir => findUp.sync('package.json', { cwd: dir }));
```
2. **Package Path Resolution**:
- Leverage `import.meta.url` with `fileURLToPath`:
```javascript
import { fileURLToPath } from 'url';
import path from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const packageRoot = path.resolve(__dirname, '..');
```
3. **Workspace-Aware Resolution**:
- Detect Yarn/pnpm workspaces:
```javascript
const findWorkspaceRoot = require('find-yarn-workspace-root');
const workspaceRoot = findWorkspaceRoot(process.cwd());
```
4. **Monorepo Handling**:
- Implement cascading configuration search
- Allow multiple tasks.json files with clear precedence rules
5. **CLI Tool Inspiration**:
- ESLint: Uses `eslint-find-rule-files` for config discovery
- Jest: Implements `jest-resolve` for custom module resolution
- Next.js: Uses `find-up` to locate project directories
6. **Robust Path Resolution Algorithm**:
```javascript
function resolveProjectRoot(startDir) {
const projectMarkers = ['package.json', '.git', 'tasks.json'];
let currentDir = startDir;
while (currentDir !== path.parse(currentDir).root) {
if (projectMarkers.some(marker => fs.existsSync(path.join(currentDir, marker)))) {
return currentDir;
}
currentDir = path.dirname(currentDir);
}
return startDir; // Fallback to original directory
}
```
7. **Environment Variable Overrides**:
- Allow users to explicitly set paths:
```javascript
const projectRoot = process.env.TASK_MASTER_PROJECT_ROOT || resolveProjectRoot(process.cwd());
```
By implementing these advanced techniques, task-master can achieve robust path handling across various npm scenarios without requiring manual specification.
</info added on 2025-04-01T02:25:01.463Z>
## 39. Implement add-dependency MCP command [done]
### Dependencies: 23.31
### Description: Create MCP tool implementation for the add-dependency command
@@ -989,3 +1136,68 @@ Analyze and refactor the project root handling mechanism to ensure consistent fi
### Details:
## 45. Support setting env variables through mcp server [pending]
### Dependencies: None
### Description: currently we need to access the env variables through the env file present in the project (that we either create or find and append to). we could abstract this by allowing users to define the env vars in the mcp.json directly as folks currently do. mcp.json should then be in gitignore if thats the case. but for this i think in fastmcp all we need is to access ENV in a specific way. we need to find that way and then implement it
### Details:
<info added on 2025-04-01T01:57:24.160Z>
To access environment variables defined in the mcp.json config file when using FastMCP, you can utilize the `Config` class from the `fastmcp` module. Here's how to implement this:
1. Import the necessary module:
```python
from fastmcp import Config
```
2. Access environment variables:
```python
config = Config()
env_var = config.env.get("VARIABLE_NAME")
```
This approach allows you to retrieve environment variables defined in the mcp.json file directly in your code. The `Config` class automatically loads the configuration, including environment variables, from the mcp.json file.
For security, ensure that sensitive information in mcp.json is not committed to version control. You can add mcp.json to your .gitignore file to prevent accidental commits.
If you need to access multiple environment variables, you can do so like this:
```python
db_url = config.env.get("DATABASE_URL")
api_key = config.env.get("API_KEY")
debug_mode = config.env.get("DEBUG_MODE", False) # With a default value
```
This method provides a clean and consistent way to access environment variables defined in the mcp.json configuration file within your FastMCP project.
</info added on 2025-04-01T01:57:24.160Z>
<info added on 2025-04-01T01:57:49.848Z>
To access environment variables defined in the mcp.json config file when using FastMCP in a JavaScript environment, you can use the `fastmcp` npm package. Here's how to implement this:
1. Install the `fastmcp` package:
```bash
npm install fastmcp
```
2. Import the necessary module:
```javascript
const { Config } = require('fastmcp');
```
3. Access environment variables:
```javascript
const config = new Config();
const envVar = config.env.get('VARIABLE_NAME');
```
This approach allows you to retrieve environment variables defined in the mcp.json file directly in your JavaScript code. The `Config` class automatically loads the configuration, including environment variables, from the mcp.json file.
You can access multiple environment variables like this:
```javascript
const dbUrl = config.env.get('DATABASE_URL');
const apiKey = config.env.get('API_KEY');
const debugMode = config.env.get('DEBUG_MODE', false); // With a default value
```
This method provides a consistent way to access environment variables defined in the mcp.json configuration file within your FastMCP project in a JavaScript environment.
</info added on 2025-04-01T01:57:49.848Z>

View File

@@ -1,102 +1,39 @@
# Task ID: 40
# Title: Implement Project Funding Documentation and Support Infrastructure
# Status: in-progress
# Title: Implement 'plan' Command for Task Implementation Planning
# Status: pending
# Dependencies: None
# Priority: medium
# Description: Create FUNDING.yml for GitHub Sponsors integration that outlines all financial support options for the Task Master project.
# Description: Create a new 'plan' command that appends a structured implementation plan to tasks or subtasks, generating step-by-step instructions for execution based on the task content.
# Details:
This task involves creating a FUNDING.yml file to enable and manage funding options for the Task Master project:
Implement a new 'plan' command that will append a structured implementation plan to existing tasks or subtasks. The implementation should:
**FUNDING.yml file**:
- Create a .github/FUNDING.yml file following GitHub's specifications
- Include configuration for multiple funding platforms:
- GitHub Sponsors (primary if available)
- Open Collective
- Patreon
- Ko-fi
- Liberapay
- Custom funding URLs (project website donation page)
- Research and reference successful implementation patterns from Vue.js, React, and TypeScript projects
- Ensure the FUNDING.yml contains sufficient information to guide users on how to support the project
- Include comments within the YAML file to provide context for each funding option
1. Accept an '--id' parameter that can reference either a task or subtask ID
2. Determine whether the ID refers to a task or subtask and retrieve the appropriate content from tasks.json and/or individual task files
3. Generate a step-by-step implementation plan using AI (Claude by default)
4. Support a '--research' flag to use Perplexity instead of Claude when needed
5. Format the generated plan within XML tags like `<implementation_plan as of timestamp>...</implementation_plan>`
6. Append this plan to the implementation details section of the task/subtask
7. Display a confirmation card indicating the implementation plan was successfully created
The implementation should maintain consistent branding and messaging with the rest of the Task Master project. Research at least 5 successful open source projects to identify best practices in funding configuration.
The implementation plan should be detailed and actionable, containing specific steps such as searching for files, creating new files, modifying existing files, etc. The goal is to frontload planning work into the task/subtask so execution can begin immediately.
Reference the existing 'update-subtask' command implementation as a starting point, as it uses a similar approach for appending content to tasks. Ensure proper error handling for cases where the specified ID doesn't exist or when API calls fail.
# Test Strategy:
Testing should verify the technical implementation of the FUNDING.yml file:
Testing should verify:
1. **FUNDING.yml validation**:
- Verify the file is correctly placed in the .github directory
- Validate YAML syntax using a linter
- Test that GitHub correctly displays funding options on the repository page
- Verify all links to external funding platforms are functional
1. Command correctly identifies and retrieves content for both task and subtask IDs
2. Implementation plans are properly generated and formatted with XML tags and timestamps
3. Plans are correctly appended to the implementation details section without overwriting existing content
4. The '--research' flag successfully switches the backend from Claude to Perplexity
5. Appropriate error messages are displayed for invalid IDs or API failures
6. Confirmation card is displayed after successful plan creation
2. **User experience testing**:
- Test the complete funding workflow from a potential supporter's perspective
- Verify the process is intuitive and barriers to contribution are minimized
- Check that the Sponsor button appears correctly on GitHub
- Ensure all funding platform links resolve to the correct destinations
- Gather feedback from 2-3 potential users on clarity and ease of use
# Subtasks:
## 1. Research and Create FUNDING.yml File [done]
### Dependencies: None
### Description: Research successful funding configurations and create the .github/FUNDING.yml file for GitHub Sponsors integration and other funding platforms.
### Details:
Implementation steps:
1. Create the .github directory at the project root if it doesn't exist
2. Research funding configurations from 5 successful open source projects (Vue.js, React, TypeScript, etc.)
3. Document the patterns and approaches used in these projects
4. Create the FUNDING.yml file with the following platforms:
- GitHub Sponsors (primary)
- Open Collective
- Patreon
- Ko-fi
- Liberapay
- Custom donation URL for the project website
5. Validate the YAML syntax using a linter
6. Test the file by pushing to a test branch and verifying the Sponsor button appears correctly on GitHub
Testing approach:
- Validate YAML syntax using yamllint or similar tool
- Test on GitHub by checking if the Sponsor button appears in the repository
- Verify each funding link resolves to the correct destination
## 4. Add Documentation Comments to FUNDING.yml [pending]
### Dependencies: 40.1
### Description: Add comprehensive comments within the FUNDING.yml file to provide context and guidance for each funding option.
### Details:
Implementation steps:
1. Add a header comment explaining the purpose of the file
2. For each funding platform entry, add comments that explain:
- What the platform is
- How funds are processed on this platform
- Any specific benefits of using this platform
- Brief instructions for potential sponsors
3. Include a comment about how sponsors will be acknowledged
4. Add information about fund allocation (maintenance, new features, infrastructure)
5. Ensure comments follow YAML comment syntax and don't break the file structure
Testing approach:
- Validate that the YAML file still passes linting with comments added
- Verify the file still functions correctly on GitHub
- Have at least one team member review the comments for clarity and completeness
## 5. Integrate Funding Information in Project README [pending]
### Dependencies: 40.1, 40.4
### Description: Add a section to the project README that highlights the funding options and directs users to the Sponsor button.
### Details:
Implementation steps:
1. Create a 'Support the Project' or 'Sponsorship' section in the README.md
2. Explain briefly why financial support matters for the project
3. Direct users to the GitHub Sponsor button
4. Mention the alternative funding platforms available
5. Include a brief note on how funds will be used
6. Add any relevant funding badges (e.g., Open Collective, GitHub Sponsors)
Testing approach:
- Review the README section for clarity and conciseness
- Verify all links work correctly
- Ensure the section is appropriately visible but doesn't overshadow project information
- Check that badges render correctly
Test cases should include:
- Running 'plan --id 123' on an existing task
- Running 'plan --id 123.1' on an existing subtask
- Running 'plan --id 123 --research' to test the Perplexity integration
- Running 'plan --id 999' with a non-existent ID to verify error handling
- Running the command on tasks with existing implementation plans to ensure proper appending
Manually review the quality of generated plans to ensure they provide actionable, step-by-step guidance that accurately reflects the task requirements.

File diff suppressed because one or more lines are too long