summaryrefslogtreecommitdiff
path: root/internal/store/native_tasks.go
AgeCommit message (Collapse)Author
2026-07-16fix(tasks): make CreateNextIteration atomically self-guardingPeter Stone
Folds the "is this still the latest row in its series?" check directly into the INSERT as a single atomic INSERT...SELECT...WHERE NOT EXISTS statement, instead of a separate SELECT-then-INSERT sequence. Closes a narrow race where the completion trigger and the periodic due-date check could both pass their "still latest" check before either had inserted, producing two duplicate successor rows for the same series. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16fix(tasks): return ErrNativeTaskNotFound from UpdateNativeTask on stale idPeter Stone
HandleWidgetTaskUpdate now returns 404 instead of silently succeeding when the widget's cached task id no longer exists, matching every other native_tasks mutator's checkRowsAffected pattern. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16feat(tasks): add periodic due-date check for recurring tasksPeter Stone
A recurring task's successor now also gets created once its due date passes, independent of completion -- an ignored/overdue recurring task no longer blocks the next occurrence from appearing. Runs every 15 minutes via a new goroutine in main.go, cancelled on shutdown.
2026-07-16feat(tasks): create the next recurring iteration on completionPeter Stone
CompleteNativeTask now creates a new row for the next occurrence when completing the latest iteration of a recurring series (using the one-shot next_occurrence_override if set, else ComputeNextOccurrence). Completing an already-superseded row (the periodic due-check beat it to creating the successor) just marks it completed, no double-create.
2026-07-16feat(tasks): add recurrence columns and model fields for native tasksPeter Stone
recurrence_series_id != "" is the real recurring indicator (IsRecurring predates this feature and is never set). Adds parseWeekdays/formatWeekdays for the comma-separated weekday-list column, and threads the five new columns through scanNativeTasks and all four existing SELECT queries. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-13Merge github/master: reconcile with parallel widget workPeter Stone
Another session pushed 27 commits in parallel covering quick-add, event detail popups, recurrence display, overdue badges, a manual refresh button, and its own fix for the same overdue-tasks bug (via a separate GetOverdueNativeTasks fetch folded into BuildTimeline, rather than widening GetNativeTasksByDateRange's bound directly). Reconciled rather than blindly taking one side: - Reverted GetNativeTasksByDateRange to its original bounded query and kept upstream's GetOverdueNativeTasks + BuildTimeline fold-in as the sole overdue mechanism for native tasks, to avoid double-counting overdue items (my widened query + their separate fetch would have both returned them). Re-pointed the regression test at the now-correct contract and added a store-level test for GetOverdueNativeTasks directly. - Kept my GetGoogleTasksByDateRange fix as-is (single unbounded query) -- upstream never touched Google Tasks overdue handling, so there's no duplication risk there. - Rewove WidgetRoot's LazyColumn structure (added for scrolling) around upstream's new header buttons, pinned all-day event rows, and the enhanced TomorrowSection, none of which were written LazyColumn-aware since that work landed on this side only. - Combined both sides' additions to TaskDetailActivity/TaskDetailSheet (description-edit detail popup + due-date reschedule label) and WidgetRepository/Actions (optimistic local removal + refresh button wiring) -- these were independent, non-overlapping features that both needed to survive. - Renumbered the migration collision: both sides independently added a migration numbered 022. Card-description was already applied to the live production DB under that filename earlier this session (migrations are tracked by filename), so it keeps 022; the recurring-event-id migration, never deployed under any name here, moves to 023. Verified: go build clean, full test suite passes (only the two pre-existing agent-handler failures and the pre-existing models package build error remain, both confirmed unrelated via git stash before this session began), and a dry run against a copy of the live production database applies both migrations cleanly with no re-run conflicts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-07-13feat(widget): editable task details, scrollable list, and overdue-task fixesPeter Stone
- Add description editing to the widget's task detail popup for doot/gtasks/trello, backed by new GET /api/widget/detail and POST /api/widget/update endpoints - Make Google Tasks and Trello cards completable via the widget (Trello completion archives the card); fix Trello description never being fetched, which meant saving could silently wipe a card's real desc - Fix google_tasks.due_date/updated_at (TEXT columns) never round-tripping through sql.NullTime, which broke cached Google Tasks reads whenever the cache was valid - Fix native-task and Google-Task date-range queries excluding anything due before the window start, which dropped incomplete tasks off the widget the moment their due day passed (the "overdue tasks disappeared" bug) - Fix native task description edits blanking the task's title - Make the widget's day list scroll (LazyColumn) instead of clipping - Optimistically remove a task from the widget immediately on completion, ahead of the authoritative background refresh Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-07-12fix(timeline): include overdue native tasks in timeline and widgetPeter Stone
GetNativeTasksByDateRange's SQL bound (due_date >= start) excluded any task overdue from a previous day before ComputeDaySection ever got a chance to mark it IsOverdue, so both the web Timeline view and the widget API (which both call BuildTimeline with start = today) silently dropped overdue tasks entirely -- only the Tasks tab (unbounded GetNativeTasks) showed them. Added GetOverdueNativeTasks and folded its results into BuildTimeline alongside the ranged fetch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-12fix(widget): surface unmatched task IDs instead of silently no-oppingPeter Stone
CompleteNativeTask/UncompleteNativeTask/RescheduleNativeTask ran a plain UPDATE ... WHERE id = ? and returned whatever error Exec gave back -- which is nil even when 0 rows match, since that's not a SQL error. A stale or wrong id from the widget looked identical to a real completion: HTTP 200, nothing changed in the database. Real incident: 1 of 3 widget completeTask taps silently no-opped this way. Now checks RowsAffected() and returns ErrNativeTaskNotFound (mirrors the existing pattern in sqlite.go's ApproveAgentSession/DenyAgentSession). HandleWidgetComplete and HandleWidgetReschedule surface this as 404 instead of a fake 200, so the widget can tell 'nothing changed' apart from 'it worked.'
2026-07-06feat: remove Todoist integration entirelyDoot Agent
Native tasks (native_tasks table) fully replace Todoist. All Todoist API code, store functions, handlers, routes, templates, and tests have been removed. Migration 021 drops the now-unused tasks cache table. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29feat: reschedule tasks from widget bottom sheetPeter Stone
Tapping a doot task shows a date picker. On confirm, POSTs to /api/widget/reschedule, updates due_date in native_tasks, refreshes widget. Reschedule button only shows for source="doot" tasks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29feat: native task management + Todoist migrationPeter Stone
Adds doot-owned task storage (native_tasks table) so tasks can be managed without Todoist. CompleteTask for 'doot' source just updates the DB — no external API call, no token dependency. Migration path: POST /settings/import-from-todoist — copies Todoist cache → native_tasks Then remove TODOIST_TOKEN from .env to disable Todoist Changes: - migration 020: native_tasks table - store: GetNativeTasks, GetNativeTasksByDateRange, GetUndatedNativeTasks, CreateNativeTask, CompleteNativeTask, UncompleteNativeTask, UpdateNativeTask, ImportFromTodoist - timeline: native tasks appear as source="doot" (teal) - handleAtomToggle: "doot" case — no external API needed - HandleWidgetComplete: method on Handler, handles "doot" natively - HandleUnifiedAdd: "doot" source creates in native_tasks - widget: "doot" tasks are completable, teal color indicator Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>