diff --git a/scripts/modules/task-manager/update-task-by-id.js b/scripts/modules/task-manager/update-task-by-id.js index b77044fc..19603897 100644 --- a/scripts/modules/task-manager/update-task-by-id.js +++ b/scripts/modules/task-manager/update-task-by-id.js @@ -190,8 +190,45 @@ function parseUpdatedTaskFromText(text, expectedTaskId, logFn, isMCP) { throw new Error('Parsed AI response is not a valid JSON object.'); } + // Preprocess the task to ensure subtasks have proper structure + const preprocessedTask = { + ...parsedTask, + status: parsedTask.status || 'pending', + dependencies: Array.isArray(parsedTask.dependencies) + ? parsedTask.dependencies + : [], + details: + typeof parsedTask.details === 'string' + ? parsedTask.details + : String(parsedTask.details || ''), + testStrategy: + typeof parsedTask.testStrategy === 'string' + ? parsedTask.testStrategy + : String(parsedTask.testStrategy || ''), + // Ensure subtasks is an array and each subtask has required fields + subtasks: Array.isArray(parsedTask.subtasks) + ? parsedTask.subtasks.map((subtask) => ({ + ...subtask, + title: subtask.title || '', + description: subtask.description || '', + status: subtask.status || 'pending', + dependencies: Array.isArray(subtask.dependencies) + ? subtask.dependencies + : [], + details: + typeof subtask.details === 'string' + ? subtask.details + : String(subtask.details || ''), + testStrategy: + typeof subtask.testStrategy === 'string' + ? subtask.testStrategy + : String(subtask.testStrategy || '') + })) + : [] + }; + // Validate the parsed task object using Zod - const validationResult = updatedTaskSchema.safeParse(parsedTask); + const validationResult = updatedTaskSchema.safeParse(preprocessedTask); if (!validationResult.success) { report('error', 'Parsed task object failed Zod validation.'); validationResult.error.errors.forEach((err) => { diff --git a/scripts/modules/task-manager/update-tasks.js b/scripts/modules/task-manager/update-tasks.js index fa048037..43b854b2 100644 --- a/scripts/modules/task-manager/update-tasks.js +++ b/scripts/modules/task-manager/update-tasks.js @@ -196,7 +196,18 @@ function parseUpdatedTasksFromText(text, expectedCount, logFn, isMCP) { ); } - const validationResult = updatedTaskArraySchema.safeParse(parsedTasks); + // Preprocess tasks to ensure required fields have proper defaults + const preprocessedTasks = parsedTasks.map((task) => ({ + ...task, + // Ensure subtasks is always an array (not null or undefined) + subtasks: Array.isArray(task.subtasks) ? task.subtasks : [], + // Ensure status has a default value if missing + status: task.status || 'pending', + // Ensure dependencies is always an array + dependencies: Array.isArray(task.dependencies) ? task.dependencies : [] + })); + + const validationResult = updatedTaskArraySchema.safeParse(preprocessedTasks); if (!validationResult.success) { report('error', 'Parsed task array failed Zod validation.'); validationResult.error.errors.forEach((err) => { @@ -442,7 +453,17 @@ async function updateTasks( data.tasks.forEach((task, index) => { if (updatedTasksMap.has(task.id)) { // Only update if the task was part of the set sent to AI - data.tasks[index] = updatedTasksMap.get(task.id); + const updatedTask = updatedTasksMap.get(task.id); + // Merge the updated task with the existing one to preserve fields like subtasks + data.tasks[index] = { + ...task, // Keep all existing fields + ...updatedTask, // Override with updated fields + // Ensure subtasks field is preserved if not provided by AI + subtasks: + updatedTask.subtasks !== undefined + ? updatedTask.subtasks + : task.subtasks + }; actualUpdateCount++; } });