Compare commits
1 Commits
fix/extern
...
fix/normal
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9aa9faf59 |
7
.changeset/pink-houses-lay.md
Normal file
7
.changeset/pink-houses-lay.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix double .taskmaster directory paths in file resolution utilities
|
||||||
|
|
||||||
|
- Closes #636
|
||||||
@@ -3,7 +3,8 @@ import {
|
|||||||
findTasksPath as coreFindTasksPath,
|
findTasksPath as coreFindTasksPath,
|
||||||
findPRDPath as coreFindPrdPath,
|
findPRDPath as coreFindPrdPath,
|
||||||
findComplexityReportPath as coreFindComplexityReportPath,
|
findComplexityReportPath as coreFindComplexityReportPath,
|
||||||
findProjectRoot as coreFindProjectRoot
|
findProjectRoot as coreFindProjectRoot,
|
||||||
|
normalizeProjectRoot
|
||||||
} from '../../../../src/utils/path-utils.js';
|
} from '../../../../src/utils/path-utils.js';
|
||||||
import { PROJECT_MARKERS } from '../../../../src/constants/paths.js';
|
import { PROJECT_MARKERS } from '../../../../src/constants/paths.js';
|
||||||
|
|
||||||
@@ -49,19 +50,24 @@ export function findPrdPath(explicitPath, args = null, log = silentLogger) {
|
|||||||
export function resolveTasksPath(args, log = silentLogger) {
|
export function resolveTasksPath(args, log = silentLogger) {
|
||||||
// Get explicit path from args.file if provided
|
// Get explicit path from args.file if provided
|
||||||
const explicitPath = args?.file;
|
const explicitPath = args?.file;
|
||||||
const projectRoot = args?.projectRoot;
|
const rawProjectRoot = args?.projectRoot;
|
||||||
|
|
||||||
// If explicit path is provided and absolute, use it directly
|
// If explicit path is provided and absolute, use it directly
|
||||||
if (explicitPath && path.isAbsolute(explicitPath)) {
|
if (explicitPath && path.isAbsolute(explicitPath)) {
|
||||||
return explicitPath;
|
return explicitPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If explicit path is relative, resolve it relative to projectRoot
|
// Normalize project root if provided
|
||||||
|
const projectRoot = rawProjectRoot
|
||||||
|
? normalizeProjectRoot(rawProjectRoot)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// If explicit path is relative, resolve it relative to normalized projectRoot
|
||||||
if (explicitPath && projectRoot) {
|
if (explicitPath && projectRoot) {
|
||||||
return path.resolve(projectRoot, explicitPath);
|
return path.resolve(projectRoot, explicitPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use core findTasksPath with explicit path and projectRoot context
|
// Use core findTasksPath with explicit path and normalized projectRoot context
|
||||||
if (projectRoot) {
|
if (projectRoot) {
|
||||||
return coreFindTasksPath(explicitPath, { projectRoot }, log);
|
return coreFindTasksPath(explicitPath, { projectRoot }, log);
|
||||||
}
|
}
|
||||||
@@ -79,19 +85,24 @@ export function resolveTasksPath(args, log = silentLogger) {
|
|||||||
export function resolvePrdPath(args, log = silentLogger) {
|
export function resolvePrdPath(args, log = silentLogger) {
|
||||||
// Get explicit path from args.input if provided
|
// Get explicit path from args.input if provided
|
||||||
const explicitPath = args?.input;
|
const explicitPath = args?.input;
|
||||||
const projectRoot = args?.projectRoot;
|
const rawProjectRoot = args?.projectRoot;
|
||||||
|
|
||||||
// If explicit path is provided and absolute, use it directly
|
// If explicit path is provided and absolute, use it directly
|
||||||
if (explicitPath && path.isAbsolute(explicitPath)) {
|
if (explicitPath && path.isAbsolute(explicitPath)) {
|
||||||
return explicitPath;
|
return explicitPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If explicit path is relative, resolve it relative to projectRoot
|
// Normalize project root if provided
|
||||||
|
const projectRoot = rawProjectRoot
|
||||||
|
? normalizeProjectRoot(rawProjectRoot)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// If explicit path is relative, resolve it relative to normalized projectRoot
|
||||||
if (explicitPath && projectRoot) {
|
if (explicitPath && projectRoot) {
|
||||||
return path.resolve(projectRoot, explicitPath);
|
return path.resolve(projectRoot, explicitPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use core findPRDPath with explicit path and projectRoot context
|
// Use core findPRDPath with explicit path and normalized projectRoot context
|
||||||
if (projectRoot) {
|
if (projectRoot) {
|
||||||
return coreFindPrdPath(explicitPath, { projectRoot }, log);
|
return coreFindPrdPath(explicitPath, { projectRoot }, log);
|
||||||
}
|
}
|
||||||
@@ -109,19 +120,24 @@ export function resolvePrdPath(args, log = silentLogger) {
|
|||||||
export function resolveComplexityReportPath(args, log = silentLogger) {
|
export function resolveComplexityReportPath(args, log = silentLogger) {
|
||||||
// Get explicit path from args.complexityReport if provided
|
// Get explicit path from args.complexityReport if provided
|
||||||
const explicitPath = args?.complexityReport;
|
const explicitPath = args?.complexityReport;
|
||||||
const projectRoot = args?.projectRoot;
|
const rawProjectRoot = args?.projectRoot;
|
||||||
|
|
||||||
// If explicit path is provided and absolute, use it directly
|
// If explicit path is provided and absolute, use it directly
|
||||||
if (explicitPath && path.isAbsolute(explicitPath)) {
|
if (explicitPath && path.isAbsolute(explicitPath)) {
|
||||||
return explicitPath;
|
return explicitPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If explicit path is relative, resolve it relative to projectRoot
|
// Normalize project root if provided
|
||||||
|
const projectRoot = rawProjectRoot
|
||||||
|
? normalizeProjectRoot(rawProjectRoot)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// If explicit path is relative, resolve it relative to normalized projectRoot
|
||||||
if (explicitPath && projectRoot) {
|
if (explicitPath && projectRoot) {
|
||||||
return path.resolve(projectRoot, explicitPath);
|
return path.resolve(projectRoot, explicitPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use core findComplexityReportPath with explicit path and projectRoot context
|
// Use core findComplexityReportPath with explicit path and normalized projectRoot context
|
||||||
if (projectRoot) {
|
if (projectRoot) {
|
||||||
return coreFindComplexityReportPath(explicitPath, { projectRoot }, log);
|
return coreFindComplexityReportPath(explicitPath, { projectRoot }, log);
|
||||||
}
|
}
|
||||||
@@ -142,13 +158,16 @@ export function resolveProjectPath(relativePath, args) {
|
|||||||
throw new Error('projectRoot is required in args to resolve project paths');
|
throw new Error('projectRoot is required in args to resolve project paths');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normalize the project root to prevent double .taskmaster paths
|
||||||
|
const projectRoot = normalizeProjectRoot(args.projectRoot);
|
||||||
|
|
||||||
// If already absolute, return as-is
|
// If already absolute, return as-is
|
||||||
if (path.isAbsolute(relativePath)) {
|
if (path.isAbsolute(relativePath)) {
|
||||||
return relativePath;
|
return relativePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve relative to projectRoot
|
// Resolve relative to normalized projectRoot
|
||||||
return path.resolve(args.projectRoot, relativePath);
|
return path.resolve(projectRoot, relativePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
} from './utils.js';
|
} from './utils.js';
|
||||||
import { complexityReportDirect } from '../core/task-master-core.js';
|
import { complexityReportDirect } from '../core/task-master-core.js';
|
||||||
import { COMPLEXITY_REPORT_FILE } from '../../../src/constants/paths.js';
|
import { COMPLEXITY_REPORT_FILE } from '../../../src/constants/paths.js';
|
||||||
import path from 'path';
|
import { findComplexityReportPath } from '../core/utils/path-utils.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the complexityReport tool with the MCP server
|
* Register the complexityReport tool with the MCP server
|
||||||
@@ -38,10 +38,18 @@ export function registerComplexityReportTool(server) {
|
|||||||
`Getting complexity report with args: ${JSON.stringify(args)}`
|
`Getting complexity report with args: ${JSON.stringify(args)}`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
|
const pathArgs = {
|
||||||
const reportPath = args.file
|
projectRoot: args.projectRoot,
|
||||||
? path.resolve(args.projectRoot, args.file)
|
complexityReport: args.file
|
||||||
: path.resolve(args.projectRoot, COMPLEXITY_REPORT_FILE);
|
};
|
||||||
|
|
||||||
|
const reportPath = findComplexityReportPath(pathArgs, log);
|
||||||
|
|
||||||
|
if (!reportPath) {
|
||||||
|
return createErrorResponse(
|
||||||
|
'No complexity report found. Run task-master analyze-complexity first.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const result = await complexityReportDirect(
|
const result = await complexityReportDirect(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,32 @@ import {
|
|||||||
} from '../constants/paths.js';
|
} from '../constants/paths.js';
|
||||||
import { getLoggerOrDefault } from './logger-utils.js';
|
import { getLoggerOrDefault } from './logger-utils.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize project root to ensure it doesn't end with .taskmaster
|
||||||
|
* This prevents double .taskmaster paths when using constants that include .taskmaster
|
||||||
|
* @param {string} projectRoot - The project root path to normalize
|
||||||
|
* @returns {string} - Normalized project root path
|
||||||
|
*/
|
||||||
|
export function normalizeProjectRoot(projectRoot) {
|
||||||
|
if (!projectRoot) return projectRoot;
|
||||||
|
|
||||||
|
// Split the path into segments
|
||||||
|
const segments = projectRoot.split(path.sep);
|
||||||
|
|
||||||
|
// Find the index of .taskmaster segment
|
||||||
|
const taskmasterIndex = segments.findIndex(
|
||||||
|
(segment) => segment === '.taskmaster'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (taskmasterIndex !== -1) {
|
||||||
|
// If .taskmaster is found, return everything up to but not including .taskmaster
|
||||||
|
const normalizedSegments = segments.slice(0, taskmasterIndex);
|
||||||
|
return normalizedSegments.join(path.sep) || path.sep;
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectRoot;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the project root directory by looking for project markers
|
* Find the project root directory by looking for project markers
|
||||||
* @param {string} startDir - Directory to start searching from
|
* @param {string} startDir - Directory to start searching from
|
||||||
@@ -80,14 +106,17 @@ export function findTasksPath(explicitPath = null, args = null, log = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Try to get project root from args (MCP) or find it
|
// 2. Try to get project root from args (MCP) or find it
|
||||||
const projectRoot = args?.projectRoot || findProjectRoot();
|
const rawProjectRoot = args?.projectRoot || findProjectRoot();
|
||||||
|
|
||||||
if (!projectRoot) {
|
if (!rawProjectRoot) {
|
||||||
logger.warn?.('Could not determine project root directory');
|
logger.warn?.('Could not determine project root directory');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Check possible locations in order of preference
|
// 3. Normalize project root to prevent double .taskmaster paths
|
||||||
|
const projectRoot = normalizeProjectRoot(rawProjectRoot);
|
||||||
|
|
||||||
|
// 4. Check possible locations in order of preference
|
||||||
const possiblePaths = [
|
const possiblePaths = [
|
||||||
path.join(projectRoot, TASKMASTER_TASKS_FILE), // .taskmaster/tasks/tasks.json (NEW)
|
path.join(projectRoot, TASKMASTER_TASKS_FILE), // .taskmaster/tasks/tasks.json (NEW)
|
||||||
path.join(projectRoot, 'tasks.json'), // tasks.json in root (LEGACY)
|
path.join(projectRoot, 'tasks.json'), // tasks.json in root (LEGACY)
|
||||||
@@ -151,14 +180,17 @@ export function findPRDPath(explicitPath = null, args = null, log = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Try to get project root from args (MCP) or find it
|
// 2. Try to get project root from args (MCP) or find it
|
||||||
const projectRoot = args?.projectRoot || findProjectRoot();
|
const rawProjectRoot = args?.projectRoot || findProjectRoot();
|
||||||
|
|
||||||
if (!projectRoot) {
|
if (!rawProjectRoot) {
|
||||||
logger.warn?.('Could not determine project root directory');
|
logger.warn?.('Could not determine project root directory');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Check possible locations in order of preference
|
// 3. Normalize project root to prevent double .taskmaster paths
|
||||||
|
const projectRoot = normalizeProjectRoot(rawProjectRoot);
|
||||||
|
|
||||||
|
// 4. Check possible locations in order of preference
|
||||||
const locations = [
|
const locations = [
|
||||||
TASKMASTER_DOCS_DIR, // .taskmaster/docs/ (NEW)
|
TASKMASTER_DOCS_DIR, // .taskmaster/docs/ (NEW)
|
||||||
'scripts/', // Legacy location
|
'scripts/', // Legacy location
|
||||||
@@ -220,14 +252,17 @@ export function findComplexityReportPath(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Try to get project root from args (MCP) or find it
|
// 2. Try to get project root from args (MCP) or find it
|
||||||
const projectRoot = args?.projectRoot || findProjectRoot();
|
const rawProjectRoot = args?.projectRoot || findProjectRoot();
|
||||||
|
|
||||||
if (!projectRoot) {
|
if (!rawProjectRoot) {
|
||||||
logger.warn?.('Could not determine project root directory');
|
logger.warn?.('Could not determine project root directory');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Check possible locations in order of preference
|
// 3. Normalize project root to prevent double .taskmaster paths
|
||||||
|
const projectRoot = normalizeProjectRoot(rawProjectRoot);
|
||||||
|
|
||||||
|
// 4. Check possible locations in order of preference
|
||||||
const locations = [
|
const locations = [
|
||||||
TASKMASTER_REPORTS_DIR, // .taskmaster/reports/ (NEW)
|
TASKMASTER_REPORTS_DIR, // .taskmaster/reports/ (NEW)
|
||||||
'scripts/', // Legacy location
|
'scripts/', // Legacy location
|
||||||
@@ -283,9 +318,13 @@ export function resolveTasksOutputPath(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Try to get project root from args (MCP) or find it
|
// 2. Try to get project root from args (MCP) or find it
|
||||||
const projectRoot = args?.projectRoot || findProjectRoot() || process.cwd();
|
const rawProjectRoot =
|
||||||
|
args?.projectRoot || findProjectRoot() || process.cwd();
|
||||||
|
|
||||||
// 3. Use new .taskmaster structure by default
|
// 3. Normalize project root to prevent double .taskmaster paths
|
||||||
|
const projectRoot = normalizeProjectRoot(rawProjectRoot);
|
||||||
|
|
||||||
|
// 4. Use new .taskmaster structure by default
|
||||||
const defaultPath = path.join(projectRoot, TASKMASTER_TASKS_FILE);
|
const defaultPath = path.join(projectRoot, TASKMASTER_TASKS_FILE);
|
||||||
logger.info?.(`Using default output path: ${defaultPath}`);
|
logger.info?.(`Using default output path: ${defaultPath}`);
|
||||||
|
|
||||||
@@ -326,9 +365,13 @@ export function resolveComplexityReportOutputPath(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Try to get project root from args (MCP) or find it
|
// 2. Try to get project root from args (MCP) or find it
|
||||||
const projectRoot = args?.projectRoot || findProjectRoot() || process.cwd();
|
const rawProjectRoot =
|
||||||
|
args?.projectRoot || findProjectRoot() || process.cwd();
|
||||||
|
|
||||||
// 3. Use new .taskmaster structure by default
|
// 3. Normalize project root to prevent double .taskmaster paths
|
||||||
|
const projectRoot = normalizeProjectRoot(rawProjectRoot);
|
||||||
|
|
||||||
|
// 4. Use new .taskmaster structure by default
|
||||||
const defaultPath = path.join(projectRoot, COMPLEXITY_REPORT_FILE);
|
const defaultPath = path.join(projectRoot, COMPLEXITY_REPORT_FILE);
|
||||||
logger.info?.(`Using default complexity report output path: ${defaultPath}`);
|
logger.info?.(`Using default complexity report output path: ${defaultPath}`);
|
||||||
|
|
||||||
@@ -369,14 +412,17 @@ export function findConfigPath(explicitPath = null, args = null, log = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Try to get project root from args (MCP) or find it
|
// 2. Try to get project root from args (MCP) or find it
|
||||||
const projectRoot = args?.projectRoot || findProjectRoot();
|
const rawProjectRoot = args?.projectRoot || findProjectRoot();
|
||||||
|
|
||||||
if (!projectRoot) {
|
if (!rawProjectRoot) {
|
||||||
logger.warn?.('Could not determine project root directory');
|
logger.warn?.('Could not determine project root directory');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Check possible locations in order of preference
|
// 3. Normalize project root to prevent double .taskmaster paths
|
||||||
|
const projectRoot = normalizeProjectRoot(rawProjectRoot);
|
||||||
|
|
||||||
|
// 4. Check possible locations in order of preference
|
||||||
const possiblePaths = [
|
const possiblePaths = [
|
||||||
path.join(projectRoot, TASKMASTER_CONFIG_FILE), // NEW location
|
path.join(projectRoot, TASKMASTER_CONFIG_FILE), // NEW location
|
||||||
path.join(projectRoot, LEGACY_CONFIG_FILE) // LEGACY location
|
path.join(projectRoot, LEGACY_CONFIG_FILE) // LEGACY location
|
||||||
|
|||||||
Reference in New Issue
Block a user