feat(tags): Complete tag support for remaining CLI commands
- Add --tag flag to update, move, and set-status commands - Ensure all task operation commands now support tag context - Fix missing tag context passing to core functions - Complete comprehensive tag-aware command coverage
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"currentTag": "master",
|
||||
"lastSwitched": "2025-06-13T07:11:05.210Z",
|
||||
"lastSwitched": "2025-06-13T07:32:07.706Z",
|
||||
"branchTagMapping": {},
|
||||
"migrationNoticeShown": true
|
||||
}
|
||||
@@ -18,7 +18,9 @@ import {
|
||||
readJSON,
|
||||
writeJSON,
|
||||
findProjectRoot,
|
||||
getCurrentTag
|
||||
getCurrentTag,
|
||||
detectCamelCaseFlags,
|
||||
toKebabCase
|
||||
} from './utils.js';
|
||||
import {
|
||||
parsePRD,
|
||||
@@ -72,7 +74,8 @@ import {
|
||||
import {
|
||||
COMPLEXITY_REPORT_FILE,
|
||||
PRD_FILE,
|
||||
TASKMASTER_TASKS_FILE
|
||||
TASKMASTER_TASKS_FILE,
|
||||
TASKMASTER_CONFIG_FILE
|
||||
} from '../../src/constants/paths.js';
|
||||
|
||||
import {
|
||||
@@ -90,7 +93,8 @@ import {
|
||||
displayApiKeyStatus,
|
||||
displayAiUsageSummary,
|
||||
displayMultipleTasksSummary,
|
||||
displayTaggedTasksFYI
|
||||
displayTaggedTasksFYI,
|
||||
displayCurrentTagIndicator
|
||||
} from './ui.js';
|
||||
|
||||
import { initializeProject } from '../init.js';
|
||||
@@ -845,11 +849,19 @@ function registerCommands(programInstance) {
|
||||
'-r, --research',
|
||||
'Use Perplexity AI for research-backed task updates'
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const fromId = parseInt(options.from, 10); // Validation happens here
|
||||
const prompt = options.prompt;
|
||||
const useResearch = options.research || false;
|
||||
const tag = options.tag;
|
||||
|
||||
const projectRoot = findProjectRoot();
|
||||
if (!projectRoot) {
|
||||
console.error(chalk.red('Error: Could not find project root.'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check if there's an 'id' option which is a common mistake (instead of 'from')
|
||||
if (
|
||||
@@ -896,13 +908,13 @@ function registerCommands(programInstance) {
|
||||
);
|
||||
}
|
||||
|
||||
// Call core updateTasks, passing empty context for CLI
|
||||
// Call core updateTasks, passing context for CLI
|
||||
await updateTasks(
|
||||
tasksPath,
|
||||
fromId,
|
||||
prompt,
|
||||
useResearch,
|
||||
{} // Pass empty context
|
||||
{ projectRoot, tag } // Pass context with projectRoot and tag
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1292,10 +1304,12 @@ function registerCommands(programInstance) {
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
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'));
|
||||
@@ -1323,7 +1337,7 @@ function registerCommands(programInstance) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await setTaskStatus(tasksPath, taskId, status, { projectRoot });
|
||||
await setTaskStatus(tasksPath, taskId, status, { projectRoot, tag });
|
||||
});
|
||||
|
||||
// list command
|
||||
@@ -1356,6 +1370,9 @@ function registerCommands(programInstance) {
|
||||
const withSubtasks = options.withSubtasks || false;
|
||||
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
|
||||
console.log(chalk.blue(`Listing tasks from: ${tasksPath}`));
|
||||
if (statusFilter) {
|
||||
console.log(chalk.blue(`Filtering by status: ${statusFilter}`));
|
||||
@@ -1410,6 +1427,9 @@ function registerCommands(programInstance) {
|
||||
const tasksPath = path.resolve(projectRoot, options.file); // Resolve tasks path
|
||||
const tag = options.tag;
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag || getCurrentTag(projectRoot) || 'master');
|
||||
|
||||
if (options.all) {
|
||||
// --- Handle expand --all ---
|
||||
console.log(chalk.blue('Expanding all pending tasks...'));
|
||||
@@ -1518,6 +1538,9 @@ function registerCommands(programInstance) {
|
||||
// Use the provided tag, or the current active tag, or default to 'master'
|
||||
const targetTag = tag || getCurrentTag(projectRoot) || 'master';
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(targetTag);
|
||||
|
||||
// Tag-aware output file naming: master -> task-complexity-report.json, other tags -> task-complexity-report_tagname.json
|
||||
const outputPath =
|
||||
options.output === COMPLEXITY_REPORT_FILE && targetTag !== 'master'
|
||||
@@ -1674,6 +1697,9 @@ function registerCommands(programInstance) {
|
||||
const tasksPath =
|
||||
options.file || path.join(projectRoot, 'tasks', 'tasks.json');
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag);
|
||||
|
||||
// Validate tasks file exists if task IDs are specified
|
||||
if (taskIds.length > 0) {
|
||||
try {
|
||||
@@ -1826,6 +1852,9 @@ ${result.result}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag || getCurrentTag(projectRoot) || 'master');
|
||||
|
||||
if (!taskIds && !all) {
|
||||
console.error(
|
||||
chalk.red(
|
||||
@@ -1914,6 +1943,11 @@ ${result.result}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(
|
||||
options.tag || getCurrentTag(projectRoot) || 'master'
|
||||
);
|
||||
|
||||
let manualTaskData = null;
|
||||
if (isManualCreation) {
|
||||
manualTaskData = {
|
||||
@@ -2004,6 +2038,9 @@ ${result.result}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag || getCurrentTag(projectRoot) || 'master');
|
||||
|
||||
await displayNextTask(tasksPath, reportPath, { projectRoot, tag });
|
||||
});
|
||||
|
||||
@@ -2041,6 +2078,9 @@ ${result.result}
|
||||
const statusFilter = options.status;
|
||||
const tag = options.tag;
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(tag || getCurrentTag(projectRoot) || 'master');
|
||||
|
||||
if (!idArg) {
|
||||
console.error(chalk.red('Error: Please provide a task ID'));
|
||||
process.exit(1);
|
||||
@@ -3247,10 +3287,12 @@ Examples:
|
||||
'--to <id>',
|
||||
'ID of the destination (e.g., "7" or "7.3"). Must match the number of source IDs if comma-separated'
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const sourceId = options.from;
|
||||
const destinationId = options.to;
|
||||
const tag = options.tag;
|
||||
|
||||
if (!sourceId || !destinationId) {
|
||||
console.error(
|
||||
@@ -3328,7 +3370,7 @@ Examples:
|
||||
fromId,
|
||||
toId,
|
||||
i === sourceIds.length - 1,
|
||||
{ projectRoot }
|
||||
{ projectRoot, tag }
|
||||
);
|
||||
console.log(
|
||||
chalk.green(
|
||||
@@ -3358,7 +3400,7 @@ Examples:
|
||||
sourceId,
|
||||
destinationId,
|
||||
true,
|
||||
{ projectRoot }
|
||||
{ projectRoot, tag }
|
||||
);
|
||||
console.log(
|
||||
chalk.green(
|
||||
|
||||
@@ -58,6 +58,30 @@ function displayTaggedTasksFYI(data) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a small, non-intrusive indicator showing the current tag context
|
||||
* @param {string} tagName - The tag name to display
|
||||
* @param {Object} options - Display options
|
||||
* @param {boolean} [options.skipIfMaster=true] - Don't show indicator if tag is 'master'
|
||||
* @param {boolean} [options.dim=false] - Use dimmed styling
|
||||
*/
|
||||
function displayCurrentTagIndicator(tag, options = {}) {
|
||||
if (isSilentMode()) return;
|
||||
|
||||
const { skipIfMaster = true, dim = false } = options;
|
||||
|
||||
// Skip display for master tag by default (since it's the default context)
|
||||
if (skipIfMaster && tag === 'master') return;
|
||||
|
||||
// Create a small, tasteful tag indicator
|
||||
const tagIcon = '🏷️';
|
||||
const tagText = dim
|
||||
? chalk.gray(`${tagIcon} tag: ${tag}`)
|
||||
: chalk.dim(`${tagIcon} tag: `) + chalk.cyan(tag);
|
||||
|
||||
console.log(tagText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a fancy banner for the CLI
|
||||
*/
|
||||
@@ -2720,5 +2744,6 @@ export {
|
||||
failLoadingIndicator,
|
||||
warnLoadingIndicator,
|
||||
infoLoadingIndicator,
|
||||
displayContextAnalysis
|
||||
displayContextAnalysis,
|
||||
displayCurrentTagIndicator
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user