| Age | Commit message (Collapse) | Author |
|
With the cancelled-context bug fixed, the refresh actually reaches Google and
the real state of the Google Tasks grant becomes visible: it answers
invalid_grant. The stored refresh token has been dead since roughly 2026-08-16.
The earlier bug had been masking this — the refresh never got far enough to be
rejected.
Settings treated the presence of a token row as "Connected", so it reported
Google Tasks as connected for a month while every fetch failed. A refresh
failure is now persisted (migration 035 adds last_error/last_error_at to
oauth_tokens) and cleared on the next success, and settings reports "connected"
only when there is no recorded failure.
invalid_grant is classified specially, because it is the one failure retrying
cannot fix: the message tells the user to reconnect, and notes that a weekly
recurrence means the OAuth client is still in Testing publishing status, where
Google expires refresh tokens after seven days. Other errors — a network blip,
a 5xx — are left as transient rather than pushing the user through consent
needlessly.
Reconnecting at /settings is still a manual step; nothing here can perform
consent on the user's behalf.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
|
|
Tapping an item outside shopping mode now opens an edit sheet. User-added items
can be renamed, moved between stores and sections, and deleted. PlanToEat items
show why they cannot be edited — the client is read-only, so presenting fields
that silently would not save is worse than saying so — and offer removal, which
marks them checked, the same mechanism shopping mode already uses.
This needed a store registry first. Stores previously existed only because some
item referenced them by name, with Trello's list names quietly acting as the
registry; removing Trello as a source made the gap visible. Without a registry
you cannot move an item into an empty store, and moving the last item out of a
store makes it vanish mid-edit. Migration 034 adds shopping_stores and
shopping_sections, seeded from the stores currently in use, and gives items a
section column — sections previously existed only as PlanToEat category
strings, so a user item could not be filed under one at all.
Registered stores and sections now appear in the list even when empty, which is
the whole point of the registry.
Two deliberate choices about destructive edges:
* Renaming a store renames it and moves its items in one transaction. Items
reference the store by name, so doing either alone orphans them.
* Deleting a store or section keeps the items, moving them to Unassigned or
clearing the section. Losing the list is far worse than re-filing an item.
* An UPDATE matching no rows is an error, not a silent success, so a stale id
cannot look like a saved edit.
Section options are rebuilt per store in the edit sheet rather than shipped as
one flat list, so a Costco item cannot be filed under a Safeway aisle.
18 new store tests, 11 handler tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
|
|
doot reads Google Calendar through a service account, by calendar ID. That
cannot consume an .ics URL, and it cannot see a calendar subscribed to inside a
personal Google account either, because Google does not allow re-sharing a
subscribed calendar. Published schedules — sports fixtures, school terms, bin
collections — are distributed almost exclusively as .ics, so none of them could
be added at all.
Feeds are now fetched on the normal calendar refresh and merged into
calendar_events alongside Google events, so the timeline, widget and everything
downstream keep seeing one list and needed no changes.
Failure handling is deliberately asymmetric. A Google error is still returned as
an error, unchanged, so an outage there surfaces. A single failing feed is
recorded against that feed and skipped, because one dead URL should not take the
whole calendar down — and last_error is shown in settings, since a feed that has
quietly stopped resolving otherwise looks identical to a team with no games
left.
The parser handles what real feeds actually contain: line unfolding, CRLF and
LF, UTC / TZID / VALUE=DATE times, and escaped text. Two details worth naming:
a TZID time is wall-clock in that zone, and reading it as UTC would put a 1:15pm
Pacific kickoff on the timeline at 1:15pm local — wrong by the offset but
entirely plausible-looking. And non-calendar content is a hard error rather than
zero events, because an HTML error page from a moved feed URL is the common
failure and "no events" reads as success.
RRULE is deliberately unsupported: every schedule feed this targets expands
recurrence itself, one VEVENT per fixture, and a correct expansion is a large
amount of subtle code. A recurring event appears once rather than wrongly.
Settings gains an add/enable/disable/remove UI. webcal:// links are accepted and
rewritten, since that is how feeds are usually advertised.
16 parser tests, 5 store tests. Verified against the real Seattle Seahawks feed:
21 events, all with valid times.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
|
|
The Trello "Shopping" board had become a dumping ground: of 24 cards, 13 had no
list at all (rendering as "Uncategorized"), and the rest were spread across
Costco, Hardware Store, "Perennial " (trailing space, so a separate store from
"Perennial") and online. Its items were read-only in doot — no rename, no move,
no delete, only hide — and its list names were doubling as an accidental store
registry, which is the only reason stores like Hardware Store existed at all.
Migration 032 imports the two groups asked for, Hardware Store and the unlisted
cards, into user_shopping_items. Costco, Perennial and online cards are left
behind. Nothing is destroyed: the cards remain in Trello, this only stops doot
displaying them. Imported rows become ordinary user items, so they also become
editable, which Trello-sourced items never were.
Trello remains the source for the other eight boards; this is only the Shopping
board feeding the shopping list.
Also updated the quick-action modal's Shopping tab, which posted source=trello
with a Trello list_id. Left alone it would have kept creating cards that no
longer appear anywhere. It now posts source=shopping with a store name, handled
by a new case in HandleUnifiedAdd, and its picker reads from a new
/partials/shopping-stores endpoint. The Trello-lists endpoint it used to call
is deleted along with its route.
Note for the edit feature still to come: stores have no existence independent
of items, so a store with nothing in it cannot be chosen. That was previously
masked by Trello's lists persisting. "Move between stores and sections" needs a
real stores/sections table.
Migration tested against a seeded snapshot of the real board, including the
trailing-space store name, other boards, replay safety and the empty-cache
no-op. Two existing tests asserting Trello check-state in shopping mode were
updated to plantoeat, the only remaining external source.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
|
|
due_date had been carrying two incompatible meanings: "this has a real
deadline" (Bills, meds, a signup cutoff) and "this is when I intend to
work on it." Chains leaned entirely on the second -- every step was
stamped due_date = now the moment it unlocked -- so a five-minute call
and a six-month certification both arrived looking overdue, and the only
way to quiet them was to hand-reschedule. The list therefore always
contained work that could not be finished that day, which made ending a
day at zero impossible by construction rather than by effort.
Splits the two apart:
- due_date keeps only its real meaning: an externally-imposed deadline.
- committed_date (new, migration 031) means "I chose this for today."
Chain steps no longer get a due date on unlock (CreateChain, advanceChain,
and the delete-promotion path), and are excluded from the undated list so
they don't simply fall through to it instead. They reach the day only by
being committed, via a "+ today" control on the chain card. Bucket-active
items get the same control. BuildTimeline pulls in committed tasks,
deduped against tasks already present for a different reason (committed
and due-today are two reasons for one row, not two rows).
Migration 031 also clears the auto-stamped due dates from open chain
steps; completed steps keep theirs as historical record.
Two supporting changes made while in here:
- Extracted the native_tasks SELECT list into nativeTaskColumns. It had
been copy-pasted into nine queries that must each agree exactly with
scanNativeTasks' field order; adding committed_date meant editing all
nine correctly or silently breaking whichever was missed.
- Extracted templateFuncMap() and added TestTemplates_AllParse. New()
only logs a warning when template parsing fails, so a malformed
template shipped silently and surfaced as a broken page at runtime.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
|
|
A weekly task not done before the next one lands is stale, not still
owed. The scheduler already created the successor regardless of
completion (deliberately, so skipping one doesn't stall the series), but
nothing retired the occurrence it replaced -- so every skipped occurrence
stayed open forever as a permanent overdue item. Live: "Bills" and
"Bones's meds" each sat in the list twice.
AdvanceDueRecurringTasks now marks the superseded occurrence abandoned
when it creates the successor. A separate flag rather than `completed`,
because these were never done and crediting them would corrupt
completion history. All four open-task queries filter it out; migration
030 adds the column and backfills the occurrences already superseded
(exactly the 2 above, verified against production before deploying).
Supersedes the earlier view-level collapse (10f9fcd, reverted in
96518ad): that kept the *earliest* open instance, which is backwards --
the stale one should go and the current one stand -- and it only hid the
row in the flat list while leaving it overdue in the timeline and widget,
which is where it was actually being seen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
|
|
Service-account auth structurally cannot see a regular user's personal
task lists (no equivalent of Calendar's per-item sharing model) --
confirmed via GetTaskLists returning exactly the service account's own
empty "My Tasks" list, never the real user's three lists. Zero rows
were ever cached in production as a result.
Adds a standard 3-legged OAuth flow: /settings/google-tasks/connect
redirects to Google's consent screen (AccessTypeOffline+ApprovalForce
so a refresh_token is always issued), /callback exchanges the code and
persists the token (new oauth_tokens table), /disconnect clears it.
GoogleTasksClient now takes an option.ClientOption instead of a
credentials file path; NewGoogleTasksOAuthClient wraps it with a
dbTokenSource that reloads/refreshes from the DB on each access-token
expiry and re-persists -- carefully preserving the original
refresh_token when Google's refresh response omits one (it usually
does), which would otherwise silently and permanently break future
refreshes.
Settings page shows connection status and a Connect/Disconnect
button. Calendar keeps using service-account auth (that one actually
works). Requires a one-time manual step: create an OAuth 2.0 Client ID
in Google Cloud Console and set GOOGLE_OAUTH_CLIENT_ID/SECRET in .env
-- documented in .env.example.
|
|
Audited it (couldn't query the live DB directly -- auto-mode classifier
blocks direct production reads without prior approval -- so this is a
code-only audit): GetFeatureToggles/SetFeatureEnabled/IsFeatureEnabled/
CreateFeatureToggle/DeleteFeatureToggle had exactly one caller each, all
inside their own CRUD handlers. Nothing anywhere else in the codebase
read a toggle's Enabled state to gate any actual behavior -- confirmed
by grepping every remaining .Enabled/IsFeatureEnabled reference back to
either this dead code or its own tests. It was pure UI-managed CRUD with
no consumer, unlike Trusted Agents (wired into agent.go/websocket.go)
or Data Sources (wired into the sync pipeline) which stayed.
Removes the Settings page section, the three /settings/features* routes
and handlers, the five Store methods, the FeatureToggle model, and adds
028_drop_feature_toggles.sql (next free migration number, per this
repo's convention of never renumbering -- see 021_drop_tasks.sql for
the same drop-table-forward pattern) to drop the now-unused table.
Also removed the now-dead tests for all of the above.
go build ./... and go test ./... both clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
|
|
Backend, web timeline, and Android widget wiring for the last two
unimplemented items from doot-future-task-scheduling-ideas.
Chains: task_chains table + chain_id/chain_position/chain_unlocked on
native_tasks (migration 026), WIP-limit-1 advancement hooked into
CompleteNativeTask, locked tasks excluded from all date-based queries,
5 new /api/widget/chains* endpoints, an N/M position badge on web and
Android widget rows.
Buckets: maintenance_buckets table + bucket_id/bucket_state/
bucket_last_active_at on native_tasks (migration 027),
staleness-then-priority selection scoring, a new RunBucketCycleCheck
scheduler loop, 5 new endpoints including the distinct Defer action, a
Defer button on web and Android widget rows.
Also corrected stale "not yet approved" status headers on the two
already-shipped specs this work depended on (labels/projects, budgets/
availability) -- their headers were never updated after implementation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
|
|
Creates migrations/025_task_budgets_and_availability.sql with:
- New availability_blocks table for manual weekly availability templates
- estimated_minutes column on native_tasks for time budgeting
- budget_tracked flag on projects and labels for opt-in tracking
Fixes pre-existing bug in sqlite_test.go's setupTestStoreWithNativeTasks where
project_id column was missing from the schema, causing test failures.
Updates all hand-rolled test helpers (sqlite_test.go, native_tasks_test.go)
to include the new columns, and adds availability_test.go with newAvailabilityTestStore
helper for Task 4's availability CRUD tests.
All store tests pass, including the two that were previously failing
(TestGetNativeTasksByDateRange_ExcludesOverdue, TestGetOverdueNativeTasks_IncludesOnlyPastDue).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PQaPGQVSfmKUiHXB87qRTC
|
|
project_id joins the existing labels JSON column as series-level
metadata: CreateNextIteration copies both onto every new recurring
occurrence, matching content/description/priority's existing behavior.
|
|
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
|
|
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
|
|
- 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
|
|
|
|
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>
|
|
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>
|
|
- Implement SQLite caching layer for Google Tasks
- Integrate Google Tasks into unified Atoms loop (showing in Tasks tab)
- Update Planning tab to include cached Google Tasks
- Enhance Quick Add form with Todoist project selector
- Remove orphaned HandleTasksTab/HandleRefreshTab methods
- Update tests to reflect new BuildTimeline signature and data structures
|
|
- Delete Bug struct, BugToAtom, SourceBug, TypeBug, TypeNote
- Remove bug store methods (SaveBug, GetBugs, ResolveBug, etc.)
- Remove HandleGetBugs, HandleReportBug, bug branches in handlers
- Remove bug routes, bugs.html template, bug UI from index.html
- Remove AddMealToPlanner stub + interface method
- Migration 018: DROP TABLE IF EXISTS bugs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
- migration 016: sync_log table
- store: AddSyncLogEntry, GetRecentSyncLog, InvalidateAllCaches, GetProjectsFromTasks
- settings: HandleClearCache (POST /settings/clear-cache), SyncLog in page data
- settings: use GetProjectsFromTasks instead of deprecated Todoist REST /projects
- handlers: populate atom projects from store
- agent: log warning on registration failure instead of silently swallowing
- google_tasks: simplify URL literal
- tests: sync log CRUD, clear cache handler, settings page includes sync log,
sync sources adds log entry, incremental sync paths, task completion
response/headers, calendar cache fallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Google Calendar events now cached via CacheFetcher pattern with
stale-cache fallback on API errors (new migration 015, store methods,
fetchCalendarEvents handler, BuildTimeline reads from store)
- Todoist incremental sync path covered by 5 new tests
- Task completion tests assert response body, headers, and template data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Enable passwordless login via passkeys as an alternative to password auth.
Users register passkeys from Settings; the login page offers both options.
WebAuthn is optional — only active when WEBAUTHN_RP_ID and WEBAUTHN_ORIGIN
env vars are set.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
- Add Development Workflow section to DESIGN.md documenting three-role
system (Architect, Implementor, Reviewer) with handoff documents
- Update CLAUDE.md with Key Documents section pointing to DESIGN.md,
role definitions, and ADRs
- Add ADR-first documentation policy across all role definitions
- Update REVIEWER_ROLE.md with comprehensive test quality checklist
- Document Agent API and completed tasks log in DESIGN.md
- Update database schema table with 5 missing tables
- Update endpoint reference with 10 missing routes
- Create ADRs 002-005 capturing key architectural decisions:
- 002: Timeline aggregation architecture
- 003: HTMX write operations pattern
- 004: Concurrent data fetching with graceful degradation
- 005: Agent API notification-based authentication
- Add migrations/README.md documenting schema history and 007 gap
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
- Add feature_toggles table (migration 012)
- Add source_config table for future source selection (migration 013)
- Create settings page at /settings with:
- Feature toggle management (enable/disable/create/delete)
- Data source configuration (sync and toggle boards/calendars)
- Add store methods for feature toggles and source config
- Add GetCalendarList and GetTaskLists to Google API clients
- Document feature toggle workflow in DESIGN.md
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
- Add completed_tasks table to log task completions with title, due date,
and completion timestamp
- Extend agent context date range: 7 days back to 14 days forward
- Add completed_log to API response (last 50 completed tasks)
- Add day_section field to timeline items (overdue/today/tomorrow/later)
- Add calendar-style view for today's schedule (6am-10pm hourly grid)
- Add tabbed interface for Timeline vs Completed Log in HTML view
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
Phase 1: Authentication and read-only context
- POST /agent/auth/request - request access with name + agent_id
- GET /agent/auth/poll - poll for approval status
- POST /agent/auth/approve|deny - user approval (browser auth required)
- GET /agent/context - 7-day timeline context (agent session required)
Phase 1.5: Browser-only agent endpoints (HTML pages)
- GET /agent/web/request - request page with token
- GET /agent/web/status - status page with polling
- GET /agent/web/context - context page with timeline data
WebSocket notifications:
- GET /ws/notifications - push agent requests to browsers
- Approval modal with trust indicators and countdown timer
Database:
- agents table for registered agent tracking
- agent_sessions table for pending/active sessions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
- #54: Fix shopping item completion - now works for all sources
(trello, plantoeat, user) with state stored in local DB
- #48: Hide 12:00am times in timeline (all-day items)
- #49: Remove "Task" type label from timeline items for cleaner UI
- #51: Combine multiple PlanToEat meals for same date+mealType
- #52: Change Conditions tab to standard link to standalone page
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
Phase 1: Bugs as First-Class Atoms (#28)
- Add resolved_at column to bugs table (migration 007)
- Add GetUnresolvedBugs(), ResolveBug(), UnresolveBug() store methods
- Include bugs in Tasks tab via BugToAtom() with completion toggle
- Add unit tests for bug resolution
Phase 2: Timeline as Default + Enhancements (#35, #37)
- Change default tab from tasks to timeline
- Add IsCompleted, DaySection, Source fields to TimelineItem
- Group timeline items by today/tomorrow/later sections
- Add completion checkboxes for tasks/cards, grey completed items
- Collapse tomorrow/later sections by default
Phase 3: Shopping Quick-Add (#33)
- Add user_shopping_items table (migration 008)
- Add SaveUserShoppingItem(), GetUserShoppingItems(), ToggleUserShoppingItem()
- Add HandleShoppingQuickAdd() and HandleShoppingToggle() handlers
- Add quick-add form to shopping tab
Phase 4: Mobile Swipe Navigation (#38)
- Add touch event handlers for swipe left/right tab switching
- 50px threshold triggers tab change
Phase 5: Consistent Background Opacity (#30)
- Add CSS variables for panel/card/input/modal backgrounds
- Update templates to use consistent opacity classes
Phase 6: Tab Reorganization (#37)
- Reorganize tabs: Timeline, Shopping, Conditions as main tabs
- Move Tasks, Planning, Meals under Details dropdown
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
- Add GoogleCalendarClient for fetching upcoming events
- Add GoogleCalendarAPI interface and CalendarEvent model
- Add config for GOOGLE_CREDENTIALS_FILE and GOOGLE_CALENDAR_ID
- Display events in Planning tab with date/time formatting
- Update handlers and tests to support optional calendar client
Config env vars:
- GOOGLE_CREDENTIALS_FILE: Path to service account JSON
- GOOGLE_CALENDAR_ID: Calendar ID (defaults to "primary")
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
Deletes 12 bug reports that have been fixed:
- Hide future tasks, modal menu, tap to expand
- terst.org styling, visual differentiation, urgency sort
- Todoist link, completed tasks, timestamp, background image
- Task edit details
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
- New bugs table in SQLite (migration 005)
- Store methods for saving and retrieving bugs
- Handlers for GET/POST /bugs
- Floating bug button with modal UI
- Shows recent bug reports in modal
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
Implement secure authentication using scs session manager with SQLite
backing store and bcrypt password hashing.
- Add users and sessions tables (migration 004)
- Create internal/auth package with Service, Middleware, and Handlers
- Protect all routes except /login, /logout, /static/*
- Add login page template and logout button to dashboard
- Default credentials: admin/changeme (configurable via env vars)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
- Add Todoist Sync API v9 support with incremental sync tokens
- Store sync tokens in SQLite for persistence across restarts
- Add field filtering to Trello API calls to reduce payload size
- Update handlers to use incremental sync (merge changes vs full replace)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
Implemented a unified web dashboard aggregating tasks, notes, and meal planning:
Core Features:
- Trello integration (PRIMARY feature - boards, cards, lists)
- Todoist integration (tasks and projects)
- Obsidian integration (20 most recent notes)
- PlanToEat integration (optional - 7-day meal planning)
- Mobile-responsive web UI with auto-refresh (5 min)
- SQLite caching with 5-minute TTL
- AI agent endpoint with Bearer token authentication
Technical Implementation:
- Go 1.21+ backend with chi router
- Interface-based API client design for testability
- Parallel data fetching with goroutines
- Graceful degradation (partial data on API failures)
- .env file loading with godotenv
- Comprehensive test coverage (9/9 tests passing)
Bug Fixes:
- Fixed .env file not being loaded at startup
- Fixed nil pointer dereference with optional API clients (typed nil interface gotcha)
Documentation:
- START_HERE.md - Quick 5-minute setup guide
- QUICKSTART.md - Fast track setup
- SETUP_GUIDE.md - Detailed step-by-step instructions
- PROJECT_SUMMARY.md - Complete project overview
- CLAUDE.md - Guide for Claude Code instances
- AI_AGENT_ACCESS.md - AI agent design document
- AI_AGENT_SETUP.md - Claude.ai integration guide
- TRELLO_AUTH_UPDATE.md - New Power-Up auth process
Statistics:
- Binary: 17MB
- Code: 2,667 lines
- Tests: 5 unit + 4 acceptance tests (all passing)
- Dependencies: chi, sqlite3, godotenv
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|