fix(tags): Resolve critical tag deletion and migration notice bugs

Major Issues Fixed:

1. Tag Deletion Bug: Fixed critical issue where creating subtasks would delete other tags

   - Root cause: writeJSON function wasn't accepting projectRoot/tag parameters

   - Fixed writeJSON signature and logic to handle tagged data structure

   - Added proper merging of resolved tag data back into full tagged structure

2. Persistent Migration Notice: Fixed FYI notice showing after every command

   - Root cause: markMigrationForNotice was resetting migrationNoticeShown to false

   - Fixed migration logic to only trigger on actual legacy->tagged migrations

   - Added proper _rawTaggedData checks to prevent false migration detection

3. Data Corruption Prevention: Enhanced data integrity safeguards

   - Fixed writeJSON to filter out internal properties

   - Added automatic cleanup of rogue properties

   - Improved hasTaggedStructure detection logic

Commands Fixed: add-subtask, remove-subtask, and all commands now preserve tags correctly
This commit is contained in:
Eyal Toledano
2025-06-12 23:43:48 -04:00
parent b3ec151b27
commit 4585a6bbc7
9 changed files with 205 additions and 75 deletions

View File

@@ -2095,11 +2095,19 @@ ${result.result}
)
.option('-s, --status <status>', 'Status for the new subtask', 'pending')
.option('--skip-generate', 'Skip regenerating task files')
.option('--tag <tag>', 'Specify tag context for task operations')
.action(async (options) => {
const projectRoot = findProjectRoot();
if (!projectRoot) {
console.error(chalk.red('Error: Could not find project root.'));
process.exit(1);
}
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
const parentId = options.parent;
const existingTaskId = options.taskId;
const generateFiles = !options.skipGenerate;
const tag = options.tag;
if (!parentId) {
console.error(
@@ -2133,7 +2141,8 @@ ${result.result}
parentId,
existingTaskId,
null,
generateFiles
generateFiles,
{ projectRoot, tag }
);
console.log(
chalk.green(
@@ -2159,7 +2168,8 @@ ${result.result}
parentId,
null,
newSubtaskData,
generateFiles
generateFiles,
{ projectRoot, tag }
);
console.log(
chalk.green(
@@ -3791,7 +3801,9 @@ async function runCLI(argv = process.argv) {
// Migration has occurred, check if we've shown the notice
let stateData = { migrationNoticeShown: false };
if (fs.existsSync(statePath)) {
stateData = readJSON(statePath) || stateData;
// Read state.json directly without tag resolution since it's not a tagged file
const rawStateData = fs.readFileSync(statePath, 'utf8');
stateData = JSON.parse(rawStateData) || stateData;
}
if (!stateData.migrationNoticeShown) {
@@ -3799,7 +3811,8 @@ async function runCLI(argv = process.argv) {
// Mark as shown
stateData.migrationNoticeShown = true;
writeJSON(statePath, stateData);
// Write state.json directly without tag resolution since it's not a tagged file
fs.writeFileSync(statePath, JSON.stringify(stateData, null, 2));
}
}
}