fix(core): Implement Boundary-First Tag Resolution (#943)
* refactor(context): Standardize tag and projectRoot handling across all task tools This commit unifies context management by adopting a boundary-first resolution strategy. All task-scoped tools now resolve `tag` and `projectRoot` at their entry point and forward these values to the underlying direct functions. This approach centralizes context logic, ensuring consistent behavior and enhanced flexibility in multi-tag environments. * fix(tag): Clean up tag handling in task functions and sync process This commit refines the handling of the `tag` parameter across multiple functions, ensuring consistent context management. The `tag` is now passed more efficiently in `listTasksDirect`, `setTaskStatusDirect`, and `syncTasksToReadme`, improving clarity and reducing redundancy. Additionally, a TODO comment has been added in `sync-readme.js` to address future tag support enhancements. * feat(tag): Implement Boundary-First Tag Resolution for consistent tag handling This commit introduces Boundary-First Tag Resolution in the task manager, ensuring consistent and deterministic tag handling across CLI and MCP. This change resolves potential race conditions and improves the reliability of tag-specific operations. Additionally, the `expandTask` function has been updated to use the resolved tag when writing JSON, enhancing data integrity during task updates. * chore(biome): formatting * fix(expand-task): Update writeJSON call to use tag instead of resolvedTag * fix(commands): Enhance complexity report path resolution and task initialization `resolveComplexityReportPath` function to streamline output path generation based on tag context and user-defined output. - Improved clarity and maintainability of command handling by centralizing path resolution logic. * Fix: unknown currentTag * fix(task-manager): Update generateTaskFiles calls to include tag and projectRoot parameters This commit modifies the `moveTask` and `updateSubtaskById` functions to pass the `tag` and `projectRoot` parameters to the `generateTaskFiles` function. This ensures that task files are generated with the correct context when requested, enhancing consistency in task management operations. * fix(commands): Refactor tag handling and complexity report path resolution This commit updates the `registerCommands` function to utilize `taskMaster.getCurrentTag()` for consistent tag retrieval across command actions. It also enhances the initialization of `TaskMaster` by passing the tag directly, improving clarity and maintainability. The complexity report path resolution is streamlined to ensure correct file naming based on the current tag context. * fix(task-master): Update complexity report path expectations in tests This commit modifies the `initTaskMaster` test to expect a valid string for the complexity report path, ensuring it matches the expected file naming convention. This change enhances test reliability by verifying the correct output format when the path is generated. * fix(set-task-status): Enhance logging and tag resolution in task status updates This commit improves the logging output in the `registerSetTaskStatusTool` function to include the tag context when setting task statuses. It also updates the tag handling by resolving the tag using the `resolveTag` utility, ensuring that the correct tag is used when updating task statuses. Additionally, the `setTaskStatus` function is modified to remove the tag parameter from the `readJSON` and `writeJSON` calls, streamlining the data handling process. * fix(commands, expand-task, task-manager): Add complexity report option and enhance path handling This commit introduces a new `--complexity-report` option in the `registerCommands` function, allowing users to specify a custom path for the complexity report. The `expandTask` function is updated to accept the `complexityReportPath` from the context, ensuring it is utilized correctly during task expansion. Additionally, the `setTaskStatus` function now includes the `tag` parameter in the `readJSON` and `writeJSON` calls, improving task status updates with proper context. The `initTaskMaster` function is also modified to create parent directories for output paths, enhancing file handling robustness. * fix(expand-task): Add complexityReportPath to context for task expansion tests This commit updates the test for the `expandTask` function by adding the `complexityReportPath` to the context object. This change ensures that the complexity report path is correctly utilized in the test, aligning with recent enhancements to complexity report handling in the task manager. * chore: implement suggested changes * fix(parse-prd): Clarify tag parameter description for task organization Updated the documentation for the `tag` parameter in the `parse-prd.js` file to provide a clearer context on its purpose for organizing tasks into separate task lists. * Fix Inconsistent tag resolution pattern. * fix: Enhance complexity report path handling with tag support This commit updates various functions to incorporate the `tag` parameter when resolving complexity report paths. The `expandTaskDirect`, `resolveComplexityReportPath`, and related tools now utilize the current tag context, improving consistency in task management. Additionally, the complexity report path is now correctly passed through the context in the `expand-task` and `set-task-status` tools, ensuring accurate report retrieval based on the active tag. * Updated the JSDoc for the `tag` parameter in the `show-task.js` file. * Remove redundant comment on tag parameter in readJSON call * Remove unused import for getTagAwareFilePath * Add missed complexityReportPath to args for task expansion * fix(tests): Enhance research tests with tag-aware functionality This commit updates the `research.test.js` file to improve the testing of the `performResearch` function by incorporating tag-aware functionality. Key changes include mocking the `findProjectRoot` to return a valid path, enhancing the `ContextGatherer` and `FuzzyTaskSearch` mocks, and adding comprehensive tests for tag parameter handling in various scenarios. The tests now cover passing different tag values, ensuring correct behavior when tags are provided, undefined, or null, and validating the integration of tags in task discovery and context gathering processes. * Remove unused import for * fix: Refactor complexity report path handling and improve argument destructuring This commit enhances the `expandTaskDirect` function by improving the destructuring of arguments for better readability. It also updates the `analyze.js` and `analyze-task-complexity.js` files to utilize the new `resolveComplexityReportOutputPath` function, ensuring tag-aware resolution of output paths. Additionally, logging has been added to provide clarity on the report path being used. * test: Add complexity report tag isolation tests and improve path handling This commit introduces a new test file for complexity report tag isolation, ensuring that different tags maintain separate complexity reports. It enhances the existing tests in `analyze-task-complexity.test.js` by updating expectations to use `expect.stringContaining` for file paths, improving robustness against path changes. The new tests cover various scenarios, including path resolution and report generation for both master and feature tags, ensuring no cross-tag contamination occurs. * Update scripts/modules/task-manager/list-tasks.js Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update scripts/modules/task-manager/list-tasks.js Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * test(complexity-report): Fix tag slugification in filename expectations - Update mocks to use slugifyTagForFilePath for cross-platform compatibility - Replace raw tag values with slugified versions in expected filenames - Fix test expecting 'feature/user-auth-v2' to expect 'feature-user-auth-v2' - Align test with actual filename generation logic that sanitizes special chars --------- Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
@@ -826,7 +826,8 @@ function registerCommands(programInstance) {
|
||||
let taskMaster;
|
||||
try {
|
||||
const initOptions = {
|
||||
prdPath: file || options.input || true
|
||||
prdPath: file || options.input || true,
|
||||
tag: options.tag
|
||||
};
|
||||
// Only include tasksPath if output is explicitly specified
|
||||
if (options.output) {
|
||||
@@ -852,8 +853,7 @@ function registerCommands(programInstance) {
|
||||
const useAppend = append;
|
||||
|
||||
// Resolve tag using standard pattern
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -966,7 +966,8 @@ function registerCommands(programInstance) {
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
|
||||
const fromId = parseInt(options.from, 10); // Validation happens here
|
||||
@@ -976,8 +977,7 @@ function registerCommands(programInstance) {
|
||||
const tasksPath = taskMaster.getTasksPath();
|
||||
|
||||
// Resolve tag using standard pattern
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -1066,13 +1066,13 @@ function registerCommands(programInstance) {
|
||||
try {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
const tasksPath = taskMaster.getTasksPath();
|
||||
|
||||
// Resolve tag using standard pattern
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -1238,13 +1238,13 @@ function registerCommands(programInstance) {
|
||||
try {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
const tasksPath = taskMaster.getTasksPath();
|
||||
|
||||
// Resolve tag using standard pattern
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -1404,11 +1404,12 @@ function registerCommands(programInstance) {
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
|
||||
const outputDir = options.output;
|
||||
const tag = options.tag;
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
console.log(
|
||||
chalk.blue(`Generating task files from: ${taskMaster.getTasksPath()}`)
|
||||
@@ -1444,12 +1445,12 @@ function registerCommands(programInstance) {
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
|
||||
const taskId = options.id;
|
||||
const status = options.status;
|
||||
const tag = options.tag;
|
||||
|
||||
if (!taskId || !status) {
|
||||
console.error(chalk.red('Error: Both --id and --status are required'));
|
||||
@@ -1465,11 +1466,9 @@ function registerCommands(programInstance) {
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Resolve tag using standard pattern and show current tag context
|
||||
const resolvedTag =
|
||||
tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
displayCurrentTagIndicator(resolvedTag);
|
||||
displayCurrentTagIndicator(tag);
|
||||
|
||||
console.log(
|
||||
chalk.blue(`Setting status of task(s) ${taskId} to: ${status}`)
|
||||
@@ -1501,7 +1500,8 @@ function registerCommands(programInstance) {
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const initOptions = {
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
};
|
||||
|
||||
// Only pass complexityReportPath if user provided a custom path
|
||||
@@ -1513,9 +1513,7 @@ function registerCommands(programInstance) {
|
||||
|
||||
const statusFilter = options.status;
|
||||
const withSubtasks = options.withSubtasks || false;
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
|
||||
@@ -1535,8 +1533,7 @@ function registerCommands(programInstance) {
|
||||
taskMaster.getComplexityReportPath(),
|
||||
withSubtasks,
|
||||
'text',
|
||||
tag,
|
||||
{ projectRoot: taskMaster.getProjectRoot() }
|
||||
{ projectRoot: taskMaster.getProjectRoot(), tag }
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1565,18 +1562,29 @@ function registerCommands(programInstance) {
|
||||
'Path to the tasks file (relative to project root)',
|
||||
TASKMASTER_TASKS_FILE // Allow file override
|
||||
) // Allow file override
|
||||
.option(
|
||||
'-cr, --complexity-report <file>',
|
||||
'Path to the report file',
|
||||
COMPLEXITY_REPORT_FILE
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
});
|
||||
const tag = options.tag;
|
||||
const initOptions = {
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
};
|
||||
|
||||
if (options.complexityReport) {
|
||||
initOptions.complexityReportPath = options.complexityReport;
|
||||
}
|
||||
|
||||
const taskMaster = initTaskMaster(initOptions);
|
||||
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(
|
||||
tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master'
|
||||
);
|
||||
displayCurrentTagIndicator(tag);
|
||||
|
||||
if (options.all) {
|
||||
// --- Handle expand --all ---
|
||||
@@ -1589,7 +1597,11 @@ function registerCommands(programInstance) {
|
||||
options.research, // Pass research flag
|
||||
options.prompt, // Pass additional context
|
||||
options.force, // Pass force flag
|
||||
{ projectRoot: taskMaster.getProjectRoot(), tag } // Pass context with projectRoot and tag
|
||||
{
|
||||
projectRoot: taskMaster.getProjectRoot(),
|
||||
tag,
|
||||
complexityReportPath: taskMaster.getComplexityReportPath()
|
||||
} // Pass context with projectRoot and tag
|
||||
// outputFormat defaults to 'text' in expandAllTasks for CLI
|
||||
);
|
||||
} catch (error) {
|
||||
@@ -1616,7 +1628,11 @@ function registerCommands(programInstance) {
|
||||
options.num,
|
||||
options.research,
|
||||
options.prompt,
|
||||
{ projectRoot: taskMaster.getProjectRoot(), tag }, // Pass context with projectRoot and tag
|
||||
{
|
||||
projectRoot: taskMaster.getProjectRoot(),
|
||||
tag,
|
||||
complexityReportPath: taskMaster.getComplexityReportPath()
|
||||
}, // Pass context with projectRoot and tag
|
||||
options.force // Pass the force flag down
|
||||
);
|
||||
// expandTask logs its own success/failure for single task
|
||||
@@ -1669,34 +1685,28 @@ function registerCommands(programInstance) {
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const initOptions = {
|
||||
tasksPath: options.file || true // Tasks file is required to analyze
|
||||
tasksPath: options.file || true, // Tasks file is required to analyze
|
||||
tag: options.tag
|
||||
};
|
||||
// Only include complexityReportPath if output is explicitly specified
|
||||
if (options.output) {
|
||||
initOptions.complexityReportPath = options.output;
|
||||
}
|
||||
|
||||
const taskMaster = initTaskMaster(initOptions);
|
||||
|
||||
const tag = options.tag;
|
||||
const modelOverride = options.model;
|
||||
const thresholdScore = parseFloat(options.threshold);
|
||||
const useResearch = options.research || false;
|
||||
|
||||
// Use the provided tag, or the current active tag, or default to 'master'
|
||||
const targetTag =
|
||||
tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const targetTag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(targetTag);
|
||||
|
||||
// Tag-aware output file naming: master -> task-complexity-report.json, other tags -> task-complexity-report_tagname.json
|
||||
const baseOutputPath =
|
||||
taskMaster.getComplexityReportPath() ||
|
||||
path.join(taskMaster.getProjectRoot(), COMPLEXITY_REPORT_FILE);
|
||||
const outputPath =
|
||||
options.output === COMPLEXITY_REPORT_FILE && targetTag !== 'master'
|
||||
? baseOutputPath.replace('.json', `_${targetTag}.json`)
|
||||
: options.output || baseOutputPath;
|
||||
// Use user's explicit output path if provided, otherwise use tag-aware default
|
||||
const outputPath = taskMaster.getComplexityReportPath();
|
||||
|
||||
console.log(
|
||||
chalk.blue(
|
||||
@@ -1777,9 +1787,12 @@ function registerCommands(programInstance) {
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (prompt, options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
});
|
||||
const initOptions = {
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
};
|
||||
|
||||
const taskMaster = initTaskMaster(initOptions);
|
||||
|
||||
// Parameter validation
|
||||
if (!prompt || typeof prompt !== 'string' || prompt.trim().length === 0) {
|
||||
@@ -1879,8 +1892,7 @@ function registerCommands(programInstance) {
|
||||
}
|
||||
}
|
||||
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -2113,17 +2125,17 @@ ${result.result}
|
||||
.action(async (options) => {
|
||||
const taskIds = options.id;
|
||||
const all = options.all;
|
||||
const tag = options.tag;
|
||||
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(
|
||||
tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master'
|
||||
);
|
||||
displayCurrentTagIndicator(tag);
|
||||
|
||||
if (!taskIds && !all) {
|
||||
console.error(
|
||||
@@ -2219,15 +2231,16 @@ ${result.result}
|
||||
// Correctly determine projectRoot
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
|
||||
const projectRoot = taskMaster.getProjectRoot();
|
||||
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master'
|
||||
);
|
||||
displayCurrentTagIndicator(tag);
|
||||
|
||||
let manualTaskData = null;
|
||||
if (isManualCreation) {
|
||||
@@ -2263,7 +2276,7 @@ ${result.result}
|
||||
|
||||
const context = {
|
||||
projectRoot,
|
||||
tag: options.tag,
|
||||
tag,
|
||||
commandName: 'add-task',
|
||||
outputType: 'cli'
|
||||
};
|
||||
@@ -2309,22 +2322,36 @@ ${result.result}
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tag = options.tag;
|
||||
const initOptions = {
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
};
|
||||
|
||||
if (options.report && options.report !== COMPLEXITY_REPORT_FILE) {
|
||||
initOptions.complexityReportPath = options.report;
|
||||
}
|
||||
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag,
|
||||
complexityReportPath: options.report || false
|
||||
});
|
||||
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
const context = {
|
||||
projectRoot: taskMaster.getProjectRoot(),
|
||||
tag
|
||||
};
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(
|
||||
tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master'
|
||||
);
|
||||
displayCurrentTagIndicator(tag);
|
||||
|
||||
await displayNextTask(
|
||||
taskMaster.getTasksPath(),
|
||||
taskMaster.getComplexityReportPath(),
|
||||
{ projectRoot: taskMaster.getProjectRoot(), tag }
|
||||
context
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2364,12 +2391,10 @@ ${result.result}
|
||||
|
||||
const idArg = taskId || options.id;
|
||||
const statusFilter = options.status;
|
||||
const tag = options.tag;
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(
|
||||
tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master'
|
||||
);
|
||||
displayCurrentTagIndicator(tag);
|
||||
|
||||
if (!idArg) {
|
||||
console.error(chalk.red('Error: Please provide a task ID'));
|
||||
@@ -2398,8 +2423,7 @@ ${result.result}
|
||||
taskIds[0],
|
||||
taskMaster.getComplexityReportPath(),
|
||||
statusFilter,
|
||||
tag,
|
||||
{ projectRoot: taskMaster.getProjectRoot() }
|
||||
{ projectRoot: taskMaster.getProjectRoot(), tag }
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -2417,17 +2441,19 @@ ${result.result}
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const initOptions = {
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
};
|
||||
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
});
|
||||
const taskMaster = initTaskMaster(initOptions);
|
||||
|
||||
const taskId = options.id;
|
||||
const dependencyId = options.dependsOn;
|
||||
|
||||
// Resolve tag using standard pattern
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -2472,17 +2498,19 @@ ${result.result}
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const initOptions = {
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
};
|
||||
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
});
|
||||
const taskMaster = initTaskMaster(initOptions);
|
||||
|
||||
const taskId = options.id;
|
||||
const dependencyId = options.dependsOn;
|
||||
|
||||
// Resolve tag using standard pattern
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -2527,14 +2555,16 @@ ${result.result}
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const initOptions = {
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
};
|
||||
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
});
|
||||
const taskMaster = initTaskMaster(initOptions);
|
||||
|
||||
// Resolve tag using standard pattern
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -2555,14 +2585,16 @@ ${result.result}
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const initOptions = {
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
};
|
||||
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
});
|
||||
const taskMaster = initTaskMaster(initOptions);
|
||||
|
||||
// Resolve tag using standard pattern
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -2583,26 +2615,21 @@ ${result.result}
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
complexityReportPath: options.file || true
|
||||
});
|
||||
const initOptions = {
|
||||
tag: options.tag
|
||||
};
|
||||
|
||||
// Use the provided tag, or the current active tag, or default to 'master'
|
||||
const targetTag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
if (options.file && options.file !== COMPLEXITY_REPORT_FILE) {
|
||||
initOptions.complexityReportPath = options.file;
|
||||
}
|
||||
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster(initOptions);
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(targetTag);
|
||||
displayCurrentTagIndicator(taskMaster.getCurrentTag());
|
||||
|
||||
// Tag-aware report file naming: master -> task-complexity-report.json, other tags -> task-complexity-report_tagname.json
|
||||
const baseReportPath = taskMaster.getComplexityReportPath();
|
||||
const reportPath =
|
||||
options.file === COMPLEXITY_REPORT_FILE && targetTag !== 'master'
|
||||
? baseReportPath.replace('.json', `_${targetTag}.json`)
|
||||
: baseReportPath;
|
||||
|
||||
await displayComplexityReport(reportPath);
|
||||
await displayComplexityReport(taskMaster.getComplexityReportPath());
|
||||
});
|
||||
|
||||
// add-subtask command
|
||||
@@ -2632,7 +2659,8 @@ ${result.result}
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
|
||||
const parentId = options.parent;
|
||||
@@ -2640,8 +2668,7 @@ ${result.result}
|
||||
const generateFiles = !options.skipGenerate;
|
||||
|
||||
// Resolve tag using standard pattern
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -2816,13 +2843,14 @@ ${result.result}
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
|
||||
const subtaskIds = options.id;
|
||||
const convertToTask = options.convert || false;
|
||||
const generateFiles = !options.skipGenerate;
|
||||
const tag = options.tag;
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
if (!subtaskIds) {
|
||||
console.error(
|
||||
@@ -3117,14 +3145,14 @@ ${result.result}
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
|
||||
const taskIdsString = options.id;
|
||||
|
||||
// Resolve tag using standard pattern
|
||||
const tag =
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master';
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
@@ -3768,12 +3796,13 @@ Examples:
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
|
||||
const sourceId = options.from;
|
||||
const destinationId = options.to;
|
||||
const tag = options.tag;
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
if (!sourceId || !destinationId) {
|
||||
console.error(
|
||||
@@ -4201,15 +4230,19 @@ Examples:
|
||||
'-s, --status <status>',
|
||||
'Show only tasks matching this status (e.g., pending, done)'
|
||||
)
|
||||
.option('-t, --tag <tag>', 'Tag to use for the task list (default: master)')
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
tasksPath: options.file || true,
|
||||
tag: options.tag
|
||||
});
|
||||
|
||||
const withSubtasks = options.withSubtasks || false;
|
||||
const status = options.status || null;
|
||||
|
||||
const tag = taskMaster.getCurrentTag();
|
||||
|
||||
console.log(
|
||||
chalk.blue(
|
||||
`📝 Syncing tasks to README.md${withSubtasks ? ' (with subtasks)' : ''}${status ? ` (status: ${status})` : ''}...`
|
||||
@@ -4219,7 +4252,8 @@ Examples:
|
||||
const success = await syncTasksToReadme(taskMaster.getProjectRoot(), {
|
||||
withSubtasks,
|
||||
status,
|
||||
tasksPath: taskMaster.getTasksPath()
|
||||
tasksPath: taskMaster.getTasksPath(),
|
||||
tag
|
||||
});
|
||||
|
||||
if (!success) {
|
||||
@@ -4941,6 +4975,33 @@ async function runCLI(argv = process.argv) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the final complexity-report path.
|
||||
* Rules:
|
||||
* 1. If caller passes --output, always respect it.
|
||||
* 2. If no explicit output AND tag === 'master' → default report file
|
||||
* 3. If no explicit output AND tag !== 'master' → append _<tag>.json
|
||||
*
|
||||
* @param {string|undefined} outputOpt --output value from CLI (may be undefined)
|
||||
* @param {string} targetTag resolved tag (defaults to 'master')
|
||||
* @param {string} projectRoot absolute project root
|
||||
* @returns {string} absolute path for the report
|
||||
*/
|
||||
export function resolveComplexityReportPath({
|
||||
projectRoot,
|
||||
tag = 'master',
|
||||
output // may be undefined
|
||||
}) {
|
||||
// 1. user knows best
|
||||
if (output) {
|
||||
return path.isAbsolute(output) ? output : path.join(projectRoot, output);
|
||||
}
|
||||
|
||||
// 2. default naming
|
||||
const base = path.join(projectRoot, COMPLEXITY_REPORT_FILE);
|
||||
return tag !== 'master' ? base.replace('.json', `_${tag}.json`) : base;
|
||||
}
|
||||
|
||||
export {
|
||||
registerCommands,
|
||||
setupCLI,
|
||||
|
||||
Reference in New Issue
Block a user