complete_task_status
Update task completion status in Task Orchestration by specifying task IDs and goal ID. Optionally complete child tasks recursively to ensure task dependencies are met.
Instructions
Update the completion status of tasks. Task IDs use a dot-notation (e.g., "1", "1.1", "1.1.1"). Responses will return simplified task objects without createdAt, updatedAt, or parentId.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| completeChildren | No | Whether to complete all child tasks recursively (boolean). Defaults to false. If false, a task can only be completed if all its subtasks are already complete. | |
| goalId | Yes | ID of the goal containing the tasks (number) | |
| taskIds | Yes | IDs of the tasks to update (array of strings). Example: ["1.1", "1.2"]. |
Implementation Reference
- src/index.ts:330-346 (handler)MCP CallToolRequest handler implementation for the 'complete_task_status' tool. Extracts input parameters and delegates to the storage layer's completeTasksStatus method to perform the updates, then returns the results as JSON.case 'complete_task_status': { const { goalId, taskIds, completeChildren } = request.params.arguments as { goalId: number; taskIds: string[]; completeChildren?: boolean; }; const results = await storage.completeTasksStatus(goalId, taskIds, completeChildren); const textContent = JSON.stringify(results, null, 2); return { content: [ { type: 'text', text: textContent, } as { type: 'text'; text: string }, ], }; }
- src/index.ts:164-189 (schema)Schema definition (inputSchema, description, and metadata) for the 'complete_task_status' tool, returned in ListTools response for registration.{ name: 'complete_task_status', description: 'Update the completion status of tasks. Task IDs use a dot-notation (e.g., "1", "1.1", "1.1.1"). Responses will return simplified task objects without `createdAt`, `updatedAt`, or `parentId`.', inputSchema: { type: 'object', properties: { goalId: { type: 'number', description: 'ID of the goal containing the tasks (number)', }, taskIds: { type: 'array', items: { type: 'string', }, description: 'IDs of the tasks to update (array of strings). Example: ["1.1", "1.2"].', }, completeChildren: { type: 'boolean', description: 'Whether to complete all child tasks recursively (boolean). Defaults to false. If false, a task can only be completed if all its subtasks are already complete.', default: false, }, }, required: ['goalId', 'taskIds'], }, },
- src/storage.ts:336-400 (handler)Core implementation of task status completion logic. Handles individual and recursive (with completeChildren) updates, enforces that tasks are only completed if subtasks are done, collects updated parents via helper, and persists changes.async completeTasksStatus( goalId: number, taskIds: string[], completeChildren: boolean = false ): Promise<{ updatedTasks: TaskResponse[]; completedParents: TaskResponse[] }> { const plan = await this.getPlan(goalId); if (!plan) { throw new Error(`No plan found for goal ${goalId}`); } const updatedTasks: TaskResponse[] = []; const completedParents: TaskResponse[] = []; const parentsToCheck: Set<string | null> = new Set(); const completeTaskAndChildren = async (taskId: string) => { const task = this.tasks.findOne({ goalId, id: taskId }); if (!task) return; // If completeChildren is true, mark all subtasks as complete first if (completeChildren) { const subtasks = this.tasks.find({ goalId, parentId: taskId }); for (const subtask of subtasks) { await completeTaskAndChildren(subtask.id); // Recursively complete children } } else { // A task can be completed only if all its non-deleted sub-tasks (if any) are completed. const subtasks = this.tasks.find({ goalId, parentId: taskId, deleted: false }); const allSubtasksComplete = subtasks.every(sub => sub.isComplete); if (!allSubtasksComplete) { console.warn(`Task ${taskId} cannot be marked complete because not all its non-deleted subtasks are complete.`); return; // Do not mark this task as complete } } // Only update if status is changing to complete if (!task.isComplete) { task.isComplete = true; task.updatedAt = new Date().toISOString(); this.tasks.update(task); const { createdAt, updatedAt, parentId: _, $loki, meta, ...taskData } = task as LokiTask; updatedTasks.push(taskData); } // Add parent to set for status check later if (task.parentId !== null) { parentsToCheck.add(task.parentId); } }; for (const taskId of taskIds) { await completeTaskAndChildren(taskId); } // After updating tasks, check and update parent statuses for (const parentId of parentsToCheck) { const completedParent = await this.updateParentTaskStatus(goalId, parentId); if (completedParent) { completedParents.push(completedParent); } } plan.updatedAt = new Date().toISOString(); await this.save(); return { updatedTasks, completedParents }; }
- src/storage.ts:205-234 (helper)Supporting utility function to propagate completion status changes from children to parent tasks, ensuring parents are complete only if all non-deleted children are complete.private async updateParentTaskStatus(goalId: number, parentId: string | null): Promise<TaskResponse | null> { if (parentId === null) return null; // Top-level tasks don't have a parent to update const parentTask = this.tasks.findOne({ goalId, id: parentId }); if (!parentTask) return null; // Only consider non-deleted child tasks for parent completion status const childTasks = this.tasks.find({ goalId, parentId, deleted: false }); const allChildrenComplete = childTasks.length > 0 && childTasks.every(task => task.isComplete); if (allChildrenComplete && !parentTask.isComplete) { parentTask.isComplete = true; parentTask.updatedAt = new Date().toISOString(); this.tasks.update(parentTask); // Use update to persist changes await this.save(); const { createdAt, updatedAt, parentId: _, $loki, meta, ...taskResponse } = parentTask; return taskResponse; } else if (!allChildrenComplete && parentTask.isComplete) { // If a non-deleted child task is marked incomplete, or a new incomplete non-deleted child is added, // the parent should also become incomplete. parentTask.isComplete = false; parentTask.updatedAt = new Date().toISOString(); this.tasks.update(parentTask); await this.save(); const { createdAt, updatedAt, parentId: _, $loki, meta, ...taskResponse } = parentTask; return taskResponse; } return null; }