summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2026-07-16fix(widget): match task font color to events; complete instantlyPeter Stone
TaskRow used a flat hardcoded gray (0xFFDDDDDD) while EventBlock used Color.White (dimmed only when past) at the same size/weight -- the color mismatch read as a font difference. Both now use the same Color.White base. CompleteTaskAction previously did no local update at all: the row stayed visible until CompleteWorker's full complete() -> fetchAndPersist() -> updateAll() round trip finished (two sequential network calls). It now optimistically removes the completed item from the cached list and re-renders immediately, matching RefreshTaskAction's existing synchronous-flag-then-updateAll pattern -- the background worker's own fetchAndPersist still replaces this with the authoritative server state (including a newly-created recurring successor, if any) moments later. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16Update worklog for widget periodic-refresh self-healing fixPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16fix(widget): re-arm periodic refresh on every onUpdate, not just onEnabledPeter Stone
onEnabled only fires when the first widget instance is added to a home screen, so if the periodic RefreshWorker job is ever silently dropped (an app reinstall can clear WorkManager's persisted schedule without the widget itself being removed/re-added -- exactly what happens when sideloading a new APK build, as opposed to a Play Store update), there was no way for it to come back except manually removing and re-adding the widget. onUpdate fires far more often (reboot, periodic OS ticks) and now also re-arms the schedule (a no-op via KEEP if already running). Root-caused via manual refresh restoring all missing content instantly (rules out a data/rendering bug) plus the widget only showing one stale morning event beforehand (consistent with the periodic job having stopped ticking hours earlier, right around today's APK reinstalls). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16Update worklog for post-recurrence fixups and dead-code cleanupPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16chore: remove dead IsRecurring field and its always-false branchPeter Stone
Task.IsRecurring/Atom.IsRecurring were never assigned anywhere in the codebase (confirmed via full-repo search), so PartitionAtomsByTime's "hide future recurring tasks until due" branch was permanently dead. RecurrenceSeriesID is the real recurring indicator now; wiring up "hide future recurring successors" as an actual feature is a separate design decision, not part of this cleanup pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16chore: remove dead code (unused atom constants, orphaned handler)Peter Stone
- SourceMeal/TypeMeal (AtomSource/AtomType): leftover from the removed MealToAtom conversion (b2d8fc4); zero references anywhere else. - HandleGetSourceOptions: never registered as a route, and its own test comment already noted "may fail if template not found, which is acceptable" -- the settings-source-options template it rendered doesn't exist in web/templates/ at all. Fully unreachable/broken, not just unused. go build/vet/test all clean, no behavior change for anything reachable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16fix(agent): restore doot-native task support in Agent API, remove stale testPeter Stone
Two independent pre-existing failures, both from incomplete refactors: - agent.go's four task write/create switches (complete/uncomplete, update due date, update details, create) never got a "doot" case added when the Todoist integration was removed (945c345) in favor of native tasks -- the test file was updated to use source=doot, but the handlers themselves still only recognized "trello"/"gtasks", so every native-task Agent API call 400'd with "Unknown source". getAtomDetails already had a "doot" case, confirming this was an incomplete migration, not an intentional gap. - TestMealToAtom in atom_test.go tested MealToAtom, a function removed from atom.go months earlier (b2d8fc4) when meals were dropped from the unified Atom/timeline system; the Meal struct itself is still used elsewhere (shopping/meals feature) but no longer produces atoms, and the test was never cleaned up to match. go test ./internal/... ./cmd/... is now fully green with no failures. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16fix(widget): remove red text color for overdue tasksPeter Stone
Overdue and non-overdue tasks now render with the same plain title color; no more red highlighting for overdue items. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
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-16Update worklog for task recurrence + detail popup editing featurePeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16feat(widget): redesign task detail popup with editing and recurrencePeter Stone
Editable title/description (Edit -> Cancel/Save toggle), linkified description, and independently-tappable date/recurrence/next-date chips. Non-doot sources (Trello, Google Tasks) are unaffected -- same title + Complete button as before, no live fetch, no edit UI.
2026-07-16feat(widget): add description linkification for URLs and phone numbersPeter Stone
2026-07-16feat(widget): add WidgetRepository methods for task detail/recurrencePeter Stone
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 HTTP endpoints for task detail, update, and recurrencePeter Stone
GET /api/widget/task, POST /api/widget/task/update, POST /api/widget/task/recurrence, POST /api/widget/task/next-date. Doot-only; the recurrence/next-date fields are null in the detail response for a non-recurring task.
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 ComputeNextOccurrence for recurring task schedulingPeter Stone
Implement pure function to compute next occurrence of recurring tasks given frequency, interval, and optional weekday constraints. Supports daily, weekly, monthly, and yearly recurrence patterns. Weekly recurrence with weekday constraints wraps to next applicable week when needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
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-16Add implementation plan for task recurrence and detail popup editingPeter Stone
Nine tasks: recurrence schema/model, ComputeNextOccurrence, iteration creation on completion, periodic due-date trigger, HTTP endpoints, Android WidgetRepository additions, description linkification, TaskDetailActivity redesign, build/deploy.
2026-07-16docs: clarify monthly rollover drift is permanent, and only affects day ↵Peter Stone
29-31 anchors
2026-07-16feat: add authenticated /docs viewer for superpowers specs/plansPeter Stone
Renders docs/superpowers/{specs,plans}/*.md to HTML via goldmark, served from doot's own web server behind the existing session auth instead of as raw files. DOCS_DIR is configurable (defaults to docs/superpowers relative to the working directory) so the deployed server can point straight at the working repo and stay live-synced with no separate copy/deploy step for new docs.
2026-07-16docs: add design for task recurrence + detail popup editingPeter Stone
New recurring-series model for doot-native tasks (server-owned, not consumer-driven): new rows are created either on completion or once a due date passes, whichever comes first. Redesigns the widget's task detail popup with editable title/description, linkified URLs/phone numbers, and independently-tappable date/recurrence/next-date chips.
2026-07-16fix(widget): fix all-day alignment, drop duplicate TODAY, boost label ↵Peter Stone
legibility, soften overdue red - AllDayRow now has the same 32dp leading gutter as HourRow's hour-label column, so its color bar lines up with EventBlock's bar in the grid below instead of sitting flush left; also dropped the title's defaultWeight() so the multi-day label sits right after the title instead of being pushed to the far-right edge. - TaskFragmentBlock no longer renders its own "TODAY" sub-header -- it's always inside the already-labeled TODAY section, and Tomorrow's floating tasks never had this redundant label to begin with. - Section headers and hour/time labels bumped from ~30-40% to ~50-60% opacity -- against a home-screen wallpaper the previous values were barely legible. - Overdue task text alpha reduced to 0.75 -- full-opacity bright red read as too alarming.
2026-07-16fix(widget): scale content font sizes down 5% across all text-size tiersPeter Stone
2026-07-16fix(widget): render multi-day starts/ends label at full opacityPeter Stone
The label was concatenated into the title string, inheriting its 0.9 alpha. Split into its own Text at full opacity, matching EventBlock's treatment of upcoming (non-past) events.
2026-07-16docs: update worklog for widget regression fixes + multi-day eventsPeter Stone
2026-07-16feat(widget): show multi-day calendar events on every day they spanPeter Stone
Multi-day events (Start and End on different calendar days) are pulled out of the normal grid/all-day pipeline and rendered as an all-day-style row on every day they touch (Today and/or Tomorrow), labeled starts/ends/plain per the day being rendered. Previously such an event either only appeared in the single hourly grid slot matching its start time (never again on later days) or, if genuinely flagged all-day, never had its End forwarded at all.
2026-07-16feat(web): render multi-day event labels in the timeline templatePeter Stone
2026-07-16fix(web): account for Google Calendar's exclusive all-day end-datePeter Stone
A single-day all-day event's End.Date is one calendar day past its own day (Google Calendar convention, already documented by TestParseEventTime_AllDayEvent). isMultiDayEvent/multiDayVariant didn't adjust for this, so every all-day event -- including single-day ones -- was misclassified as multi-day and duplicated across Today and Tomorrow.
2026-07-16docs: fix exclusive all-day end-date bug in multi-day plan's Android taskPeter Stone
MD-Task 2's review caught that Google Calendar's all-day End.Date is exclusive (a single-day all-day event's End is one day past its own day), which isMultiDayEvent/multiDayVariant didn't account for. Task 4 (Android, not yet implemented) had the same flaw copied into its Kotlin code -- fixed here before dispatching, mirroring the Go-side fix.
2026-07-16feat(web): show multi-day calendar events on every day they spanPeter Stone
TimelineItemView wraps a TimelineItem with a per-render-day MultiDayVariant (starts/ends/spans/none). HandleTimeline's bucketing now places a multi-day event into both TodayItems and TomorrowItems when it touches both, instead of only the list matching its start day.
2026-07-16fix(widget): forward End for all-day multi-day calendar eventsPeter Stone
A genuine all-day Google Calendar event spanning multiple days (e.g. a 3-day conference) never got its EndTime forwarded to the widget client, since the conversion only set End when !IsAllDay. The client has no way to detect a multi-day span without both Start and End.
2026-07-16docs: add multi-day calendar events implementation planPeter Stone
2026-07-16feat(widget): tap event to open its source directly, drop detail popupPeter Stone
Tapping a calendar event (or any event-type item) now opens the event's URL (Google Calendar, Plan to Eat, etc.) directly instead of showing an intermediate popup with an "Open in Calendar" button. Removes EventDetailActivity and the recurrence-schedule lookup it was the only consumer of: WidgetRepository.getRecurrence, the Go /api/widget/recurrence endpoint, HandleWidgetRecurrence, GoogleCalendarAPI.GetRecurrenceRule, and formatRecurrence, plus their tests. RecurringEventID itself stays -- it's general calendar-sync metadata used elsewhere in the timeline pipeline, not exclusive to the removed popup.
2026-07-16fix(widget): give Text Size label and chip labels explicit colorsPeter Stone
These were the only labels in the settings screen without an explicit color, unlike the rest of the screen's text elements.
2026-07-16fix(widget): floor header text size/weight at NORMAL even when SMALLPeter Stone
Headers (hour labels, section titles) shrinking along with content at the SMALL setting made them too small relative to content. Content still shrinks at SMALL; headers now stay at NORMAL's scale/weight regardless of the selected tier.
2026-07-16fix(widget): give popup activities distinct taskAffinityPeter Stone
TaskDetailActivity, QuickAddActivity, and EventDetailActivity shared the app's default task affinity with SettingsActivity. FLAG_ACTIVITY_NEW_TASK reuses an existing task with matching affinity rather than creating a fresh one, so if SettingsActivity's task was still alive in recents, these translucent popups rendered on top of it instead of the home screen behind them, as the theme's transparency was designed to show.
2026-07-16chore(widget): remove dead sp importPeter Stone
Unused after threading WidgetTextSize's scaling functions through every Text() call site that previously used a literal .sp value.
2026-07-16docs: update worklog for widget tomorrow-fix + text-size featurePeter Stone
2026-07-16fix(widget): restore trailing-slash trim on Test button's URLPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16feat(widget): add Small/Normal/Large text size picker to widget settingsPeter Stone
2026-07-16feat(widget): thread WidgetTextSize through all widget text renderingPeter Stone
2026-07-16feat(widget): add WidgetTextSize enum with independent header/content scalingPeter Stone
2026-07-16test(widget): pin JVM default timezone in DootWidgetGridTest for determinismPeter Stone
2026-07-16fix(widget): stop tomorrow's events from stretching today's grid boundsPeter Stone
calcGridStart/calcGridEnd only looked at hour-of-day, so a tomorrow event's early or late hour could inflate today's grid range with empty rows, pushing the non-scrolling TomorrowSection below the widget's visible area. Filter to today-only events before computing bounds.
2026-07-16docs: add widget text-size + tomorrow-section fix implementation planPeter Stone
2026-07-16docs: add design for widget text-size setting + tomorrow-section fixPeter Stone
Covers the root cause for the missing TOMORROW section (grid bounds skewed by tomorrow's events) and the configurable header/content text size+weight preference.
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