v017 polish (#778)

* fix(research, tasks): Make research command and task updates tag-aware

* refactor(tasks): Prevent automatic task file generation across other locations

This commit refactors several core task management functions to prevent them from automatically regenerating individual task files after modifying the main `tasks.json`.

Previously, operations like `add-task`, `clear-subtasks`, `expand-task`, and `update-task-by-id` would immediately trigger `generateTaskFiles`. This could be slow and was often unnecessary.

The calls to `generateTaskFiles` have been removed or commented out from the core task functions. Users should now run `task-master generate` explicitly to update their individual task files.

Additionally, this commit includes fixes to the `move` command to make it fully tag-aware.

* fix: move and clear subtasks mcp commands

* chore: fix format

* chore: fix unit tests

---------

Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com>
This commit is contained in:
Eyal Toledano
2025-06-14 20:37:25 -04:00
committed by Ralph Khreish
parent 44eba3f7d1
commit 5119cd2d8e
24 changed files with 1076 additions and 312 deletions

View File

@@ -107,8 +107,13 @@ async function performResearch(
let autoDiscoveredIds = [];
try {
const tasksPath = path.join(projectRoot, 'tasks', 'tasks.json');
const tasksData = await readJSON(tasksPath);
const tasksPath = path.join(
projectRoot,
'.taskmaster',
'tasks',
'tasks.json'
);
const tasksData = await readJSON(tasksPath, projectRoot);
if (tasksData && tasksData.tasks && tasksData.tasks.length > 0) {
// Flatten tasks to include subtasks for fuzzy search
@@ -250,6 +255,9 @@ async function performResearch(
const tagInfo = aiResult.tagInfo;
// Format and display results
// Initialize interactive save tracking
let interactiveSaveInfo = { interactiveSaveOccurred: false };
if (outputFormat === 'text') {
displayResearchResults(
researchResult,
@@ -265,7 +273,7 @@ async function performResearch(
// Offer follow-up question option (only for initial CLI queries, not MCP)
if (allowFollowUp && !isMCP) {
await handleFollowUpQuestions(
interactiveSaveInfo = await handleFollowUpQuestions(
options,
context,
outputFormat,
@@ -308,7 +316,8 @@ async function performResearch(
detailLevel,
telemetryData,
tagInfo,
savedFilePath
savedFilePath,
interactiveSaveOccurred: false // MCP save-to-file doesn't count as interactive save
};
}
@@ -325,7 +334,9 @@ async function performResearch(
totalInputTokens,
detailLevel,
telemetryData,
tagInfo
tagInfo,
interactiveSaveOccurred:
interactiveSaveInfo?.interactiveSaveOccurred || false
};
} catch (error) {
logFn.error(`Research query failed: ${error.message}`);
@@ -643,6 +654,8 @@ async function handleFollowUpQuestions(
initialQuery,
initialResult
) {
let interactiveSaveOccurred = false;
try {
// Import required modules for saving
const { readJSON } = await import('../utils.js');
@@ -693,12 +706,15 @@ async function handleFollowUpQuestions(
if (action === 'save') {
// Handle save functionality
await handleSaveToTask(
const saveResult = await handleSaveToTask(
conversationHistory,
projectRoot,
context,
logFn
);
if (saveResult) {
interactiveSaveOccurred = true;
}
continue;
}
@@ -762,6 +778,8 @@ async function handleFollowUpQuestions(
// silently continue without follow-up functionality
logFn.debug(`Follow-up questions not available: ${error.message}`);
}
return { interactiveSaveOccurred };
}
/**
@@ -828,8 +846,10 @@ async function handleSaveToTask(
return;
}
// Validate ID exists
const data = readJSON(tasksPath, projectRoot);
// Validate ID exists - use tag from context
const { getCurrentTag } = await import('../utils.js');
const tag = context.tag || getCurrentTag(projectRoot) || 'master';
const data = readJSON(tasksPath, projectRoot, tag);
if (!data || !data.tasks) {
console.log(chalk.red('❌ No valid tasks found.'));
return;
@@ -863,7 +883,7 @@ async function handleSaveToTask(
trimmedTaskId,
conversationThread,
false, // useResearch = false for simple append
context,
{ ...context, tag },
'text'
);
@@ -890,7 +910,7 @@ async function handleSaveToTask(
taskIdNum,
conversationThread,
false, // useResearch = false for simple append
context,
{ ...context, tag },
'text',
true // appendMode = true
);
@@ -899,9 +919,12 @@ async function handleSaveToTask(
chalk.green(`✅ Research conversation saved to task ${trimmedTaskId}`)
);
}
return true; // Indicate successful save
} catch (error) {
console.log(chalk.red(`❌ Error saving conversation: ${error.message}`));
logFn.error(`Error saving conversation: ${error.message}`);
return false; // Indicate failed save
}
}