summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
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
2026-07-12feat(widget): add event detail popup showing recurrence schedulePeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-12feat(widget): add recurrence lookup endpoint (GET /api/widget/recurrence)Peter Stone
2026-07-12feat(widget): capture and forward RecurringEventID for calendar eventsPeter Stone
2026-07-12fix(widget): add IME handling to quick-add's keyboard-covering input fieldPeter Stone
2026-07-12feat(widget): add quick-add button and entry sheetPeter Stone
2026-07-12feat(widget): add POST /api/widget/add for quick-addPeter Stone
2026-07-12feat(widget): make the due-date display the reschedule tap targetPeter Stone
2026-07-12docs: add widget recurrence-display implementation planPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-12feat(widget): add DueDate field for doot tasks to the widget APIPeter Stone
2026-07-12docs: add widget refresh button implementation planPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-12docs: add widget recurrence-display design specPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-12docs: add widget quick-add implementation planPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-12docs: add widget quick-add design specPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-12feat(widget): color overdue task titles distinctlyPeter Stone
2026-07-12docs: add widget clickable-reschedule implementation planPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-12feat(widget): forward IsOverdue from TimelineItem to WidgetItem APIPeter Stone
2026-07-12docs: add widget clickable-reschedule design specPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-12docs: add widget overdue-badge design spec and implementation planPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-12feat(widget): add manual refresh button with loading-state iconPeter Stone
2026-07-12docs: add widget refresh button design specPeter Stone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
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(calendar): split comma-joined GOOGLE_CALENDAR_ID before usePeter Stone
fetchCalendarEvents falls back to config.GoogleCalendarID whenever no source_configs rows exist yet for the gcal source -- which is the current live state (0 rows). GoogleCalendarID is a single env var that itself holds a comma-separated list of calendar IDs, but the whole joined string was being wrapped in a single-element []string{...} and passed straight to SetCalendarIDs. Google's API takes one calendarId per call, so every fetch failed with '404 Not Found' on the literal comma-joined string -- confirmed live in production logs. This broke all calendar events, in both the web dashboard and the widget, silently. Now splits on commas and trims whitespace before use.
2026-07-12fix(widget): pin all-day calendar events to the top instead of losing themPeter Stone
WidgetItem.isAllDay was carried by the client's data model but nothing ever read it. All-day events had no Start at all, so they fell into the same floating-task queue as ordinary untimed tasks; if enough tasks were ahead of one in the queue, SlotPacker could assign it an hour slot past the visible grid range entirely -- not merely unpinned, actually invisible. Server: TimelineItemToWidgetItem now populates Start for all-day CALENDAR EVENTS specifically (their real event date), while leaving undated doot/gtask tasks -- also flagged IsAllDay as a "no specific time" fallback, a different concept -- on the existing nil-Start floating behavior. Client: all-day events are filtered out of the hourly grid/floating-task pipeline entirely, bucketed by day using the new Start date, and rendered in a new pinned AllDayRow section right after the TODAY/TOMORROW headers.
2026-07-12fix(widget): dedup rapid completeTask taps on the same taskPeter Stone
CompleteWorker.enqueue used a plain WorkManager.enqueue(), which allows unlimited concurrent OneTimeWorkRequests. A rapid double-tap on the same row (plausible since the checkbox doesn't visually update until the full async round-trip -- complete() -> fetchAndPersist() -> updateAll() -- finishes) could spawn two independent, unordered CompleteWorker runs for the same task, each doing its own fetchAndPersist(); a second worker's fetch started before the first worker's complete() call had actually landed server-side could persist a stale snapshot after the first worker's correct one. Now uses enqueueUniqueWork("complete_$id", KEEP, ...) so a tap on a task that already has a completion in flight is dropped rather than racing a second worker. Different task ids remain independent.
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-06fix(widget): separate checkbox and row clickables to fix completeTask tapClaudomator Agent
In Glance 1.1.0 (RemoteViews), a parent Row with .clickable() silently overrides any nested child .clickable() — tapping the checkbox fired the detail-open action instead of CompleteTaskAction, producing no visible effect. Fix by splitting TaskRow into two sibling Boxes: a 24dp tap target wrapping the checkbox icon (routes to CompleteTaskAction) and a defaultWeight Box for the title (routes to actionStartActivity). No nesting, so both actions are independently reachable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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-07-05fix(deploy): add CSS build step before rsync to prevent missing output.cssClaudomator Agent
Both deploy scripts now run `npm ci || npm install && npm run build` before syncing web/static/, ensuring Tailwind output.css is always present in fresh checkouts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05Merge deploy/master (gateway/proxy fixes) with doot-native task completion fixPeter Stone
Reconciles diverged histories: deploy/master had gateway proxy Host-header and publicPaths fixes that were never synced back to local/github; this branch had the native-task Tasks-tab/completion fix. Merging both.
2026-07-05fix: native tasks missing from Tasks tab and blank title on completionDoot Agent
Bug 1: BuildUnifiedAtomList never called GetNativeTasks(), so doot-sourced tasks were absent from the web Tasks tab. Added GetNativeTasks() fetch and NativeTaskToAtom conversion (new model helper, SourceDoot constant). Bug 2: handleAtomToggle called getAtomDetails after CompleteNativeTask, but GetNativeTasks filters WHERE completed=0, so the task was already gone and the title came back blank. Moved getAtomDetails call to before the completion switch so all sources (including doot) capture title/dueDate first. Also fixed widget_test.go compile error: TestHandleWidgetComplete_NonTodoist called HandleWidgetComplete as a package-level function but it is a method on *Handler. Rewrote the file as package handlers (internal) and construct &Handler{} directly. Regression tests added for both bugs in atoms_test.go and handlers_test.go. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05fix(proxy): set Host header to upstream target to satisfy loopback MCP ↵Peter Stone
DNS-rebinding check mcp.NewStreamableHTTPHandler rejects requests where the server is bound to loopback but the Host header is not (DNS-rebinding protection). Requests proxied through doot arrived at claudomator with Host: doot.terst.org, triggering a 403. Set req.Host = target.Host in the ReverseProxy Director so upstream services see the target host (e.g. 127.0.0.1:8484) rather than the original public hostname.
2026-07-05feat(gateway): add publicPaths bypass for all-method service routesPeter Stone
Adds a publicPaths field to serviceMount alongside webhookPaths. webhookPaths remains POST-only (HMAC-signed webhooks). publicPaths bypasses session auth for all methods, relying on the upstream service's own bearer-token auth instead. Used to expose /claudomator/chatbot/mcp for MCP client connections (claude-code) which carry their own Authorization header and cannot carry a doot session cookie.
2026-06-29fix: calendar/meals sync, tomorrow flat layout, /health endpointPeter Stone
- Calendar: fall back to GOOGLE_CALENDAR_ID config when no source_configs synced yet (fixes blank calendar after fresh deploy) - Meals: call fetchMeals in HandleTimeline so PlanToEat cache refreshes on every timeline load, not just during manual refresh - Tomorrow section: replace calendar-grid with flat chronological list matching widget layout (time label | source bar | title) - Add /health endpoint (no auth required) for deploy health checks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29feat: show tomorrow section in widget; note web viewPeter Stone
Widget now renders a TOMORROW block below the today grid: events with inline time labels (slightly dimmed) and task rows. Separated by a divider. Covers both explicit-start tomorrow items and slot-packed fragments that overflow from today. Web view: TODO comment to flatten the tomorrow section to match widget. 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: make Todoist optional, guard nil client callsPeter Stone
TODOIST_API_KEY is no longer required — native task management works without it. Guards nil todoistClient in handleAtomToggle. 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>