Report effective completion date on parent-completed subtasks - #6
Conversation
…erId null on completed tasks list_tasks didn't expose a completed task's completionDate (only get_task did), and there was no way to filter by completion date server-side. Added completionDate to list_tasks' output and a completedAfter (ISO datetime) filter, following the existing dueBeforeDate pattern. Separately, list_tasks and get_task both resolved a task's containerId/ containerType via assignedContainer, which comes back null for completed tasks. Other write-path snippets (move_task, complete_task, create_task, edit_task, drop_task) already avoid this via parentTask/containingProject instead -- move_task.js even has a comment noting assignedContainer "doesn't update after moveTasks". Applied the same fix to list_tasks and get_task so completed tasks resolve their container correctly too. package-lock.json also resyncs to package.json's current name/version (0.1.0 -> @scardis/omnifocus-mcp@0.1.2), which had drifted.
…tial field Closes TECH-017 Gaps 1 & 2: - list_tasks/get_task/create_task/edit_task/drop_task/complete_task now return dropDate (via effectiveDropDate); list_tasks gains a droppedAfter filter, mirroring the completionDate/completedAfter pattern. - create_task/edit_task deferDate/plannedDate/dueDate accept a bare YYYY-MM-DD date, resolved to local midnight instead of JS's default of UTC midnight — a defer-today task is now Available immediately rather than only after the local UTC-offset hour. - create_task/edit_task can set a task's own sequential (parallel/ordered subtasks); surfaced on all task-detail responses. - move_task's inline response object was missing completionDate/dropDate entirely (a pre-existing gap once TaskSummary made completionDate required); added both for consistency.
…tasks A parent-completed child task reports status "complete" but its own completionDate stays null (only the parent's own completionDate is set), so any completedAfter scan silently misses it. Switched every task snippet's completionDate output from task.completionDate to task.effectiveCompletedDate, which OmniFocus populates from the parent's completion when the task's own is unset (confirmed live: matches completionDate exactly for a normally-completed task, so no behaviour change there). Fixes list_tasks/get_task/create_task/edit_task/drop_task/ complete_task/move_task.
|
Reviewed against current Merge hazard: this PR's
|
…equirement - Resolve the package.json merge conflict by taking main's copy wholesale, so this branch no longer reintroduces vitest ^2.1.0 (CVE-2025-24964), the tsc-only build (dropping copy:snippets), or src/snippets/ in files. Regenerate package-lock.json with npm install so its root version matches (0.2.1). - Document on completedAfter/droppedAfter (both the field .describe() and the list_tasks tool description) that complete/dropped tasks are excluded by default, so each filter returns nothing unless status is widened to include "complete"/"dropped". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks for the thorough review — all addressed. Pushed as a merge of current
Integration suite passes on this branch against a live OmniFocus database on macOS: 100/100 (28 files), including the On the |
Stacked on #2 and #5 — this branch is built on top of
tech-017-drop-defer-sequential(open as #5, itself stacked on #2), so this diff currently includes both of those commits too. Once #2 and #5 merge, this PR's diff will shrink to just the commit below.Completing a parent task effectively completes its children too, but a child's own
completionDatestaysnull— only the parent's owncompletionDategets set. AnycompletedAfterscan (list_tasks {status: ["complete"], completedAfter}) therefore silently misses parent-completed subtasks, since anullcompletionDate can never satisfy the filter.Switched every task snippet's
completionDateoutput (list_tasks/get_task/create_task/edit_task/drop_task/complete_task/move_task) fromtask.completionDatetotask.effectiveCompletedDate, which OmniFocus populates from the parent's completion when the task's own is unset.Verified before shipping that this introduces no regression:
effectiveCompletedDatematchescompletionDateexactly.completionDate/effectiveCompletedDatein agreement (no divergence), so this fix doesn't interact badly with recurrence.Test plan
npm test— 151 unit tests passnpm run test:integration— 99/99 pass, including new dedicated coverage (effectiveCompletionDate.int.test.ts) reproducing the exact parent/child scenario.mcpblocally; verified live against a real OmniFocus database — completing a parent task now makesget_task(child)return a realcompletionDate, andlist_tasks {status:["complete"], completedAfter}correctly returns both parent and child (previously only the parent)