summaryrefslogtreecommitdiff
path: root/.agent
diff options
context:
space:
mode:
Diffstat (limited to '.agent')
-rw-r--r--.agent/coding_standards.md70
-rw-r--r--.agent/config.md62
-rw-r--r--.agent/design.md831
-rw-r--r--.agent/mission.md16
-rw-r--r--.agent/narrative.md32
-rw-r--r--.agent/preferences.md15
-rw-r--r--.agent/timeline_design.md82
-rw-r--r--.agent/ux_philosophy.md82
-rw-r--r--.agent/worklog.md81
9 files changed, 1271 insertions, 0 deletions
diff --git a/.agent/coding_standards.md b/.agent/coding_standards.md
new file mode 100644
index 0000000..50281d0
--- /dev/null
+++ b/.agent/coding_standards.md
@@ -0,0 +1,70 @@
+# Coding Standards
+
+This document defines the technical standards for the **Doot** project. Adherence to these standards ensures consistency, security, and maintainability.
+
+## 1. Go (Backend)
+
+### Idiomatic Go
+- Follow standard Go idioms (Effective Go).
+- Keep functions small and focused on a single responsibility.
+- Use meaningful, descriptive names for variables, functions, and types.
+
+### Concurrency
+- Use `sync.WaitGroup` and `sync.Mutex` for managing concurrent operations.
+- For parallel API fetching, use a semaphore pattern (e.g., buffered channel) to limit concurrency and avoid rate limits.
+- **Example:** See `internal/api/trello.go` for the 5-request concurrency limit.
+
+### Error Handling
+- Use the "Partial Data / Cache Fallback" pattern: If an API call fails, return cached data (if available) or an empty set with an error logged, rather than failing the entire request.
+- Use structured logging or the `data.Errors` slice in handlers to report non-fatal errors to the UI.
+
+### Database (SQLite)
+- **SQL Injection Prevention:** ALWAYS use parameterized queries (`?` placeholders).
+- **Concurrency:** Enable WAL mode and set `MaxOpenConns(1)` to avoid "database is locked" errors.
+- **Migrations:** All schema changes must be added as a new file in the `migrations/` directory.
+
+### Project Structure
+- `cmd/dashboard/`: Application entry point.
+- `internal/api/`: External service clients (Todoist, Trello, etc.).
+- `internal/auth/`: Authentication logic and middleware.
+- `internal/config/`: Configuration loading and validation.
+- `internal/handlers/`: HTTP request handlers and UI logic.
+- `internal/models/`: Shared data structures.
+- `internal/store/`: Database operations.
+
+## 2. Frontend (HTMX + Tailwind CSS)
+
+### HTMX
+- Use HTMX for all state-changing operations (Create, Update, Delete) and tab switching.
+- **Response Headers:** Use `HX-Trigger` and `HX-Reswap` to coordinate UI updates.
+- **Partial Rendering:** Handlers should return HTML partials (from `web/templates/partials/`) for HTMX requests.
+
+### CSS & Styling
+- Use **Tailwind CSS** for all styling.
+- Maintain a consistent mobile-first responsive design.
+- Follow the Z-index hierarchy defined in `design.md`.
+
+### User Feedback
+- Provide immediate visual feedback for user actions (loading indicators, success/error banners).
+- Ensure all forms clear their inputs upon successful submission.
+
+## 3. Testing Philosophy
+
+### Reproduction First
+- Before fixing a bug, implement a failing test case that reproduces the issue.
+- Verify the fix by ensuring the new test (and all existing tests) passes.
+
+### Coverage Areas
+- **Store:** Unit tests for all SQL operations (`sqlite_test.go`).
+- **Handlers:** Integration tests for critical paths (`handlers_test.go`, `agent_test.go`).
+- **API Clients:** Use mocks or test servers for external API testing (`todoist_test.go`, `trello_test.go`).
+
+## 4. Documentation & Git
+
+### Commit Messages
+- Propose clear, concise messages that explain the "why" behind the change.
+- Match existing style (usually imperative mood).
+
+### File Header
+- Maintain the standardized `SESSION_STATE.md` (now `worklog.md`) format.
+- Document significant architectural changes in `docs/adr/`.
diff --git a/.agent/config.md b/.agent/config.md
new file mode 100644
index 0000000..45ead3b
--- /dev/null
+++ b/.agent/config.md
@@ -0,0 +1,62 @@
+# Agent Configuration & Master Rulebook (.agent/config.md)
+
+This is the primary source of truth for all AI agents working on **Doot**. These instructions take absolute precedence over general defaults.
+
+## 1. Project Directory Structure (.agent/)
+
+| File | Purpose |
+|------|---------|
+| `config.md` | **Main Entry Point** — Rules, workflows, and core mandates. |
+| `worklog.md` | **Session State** — Current focus, recently completed, and next steps. |
+| `design.md` | **Architecture** — High-level design, database schema, and components. |
+| `coding_standards.md` | **Technical Standards** — Go/HTMX idioms, testing, and security. |
+| `ux_philosophy.md` | **UX Principles** — Interaction models, palette, and mobile-first design. |
+| `narrative.md` | **Background** — Historical context and evolution of the project. |
+
+## 2. Core Mandates
+
+### ULTRA-STRICT ROOT SAFETY PROTOCOL
+1. **Inquiry-Only Default:** Treat every message as research/analysis unless it is an explicit, imperative command (Directive).
+2. **Zero Unsolicited Implementation:** Never modify files, directories, or processes based on assumptions.
+3. **Interactive Strategy Checkpoint:** Research first, present a strategy, and **WAIT** for an explicit "GO" before any system-changing tool call.
+4. **No Destructive Assumptions:** Always verify state (`ps`, `ls`, `git status`) before proposing actions.
+5. **Root-Awareness:** Prioritize system integrity and user confirmation over proactiveness.
+
+### Task Management
+- **Worklog:** Update `.agent/worklog.md` at the start and end of every session.
+- **Claudomator:** Use `claudomator create "Name" --instructions "Goals"` for new tasks. Use `claudomator finish <id>` when done.
+
+### Living Documentation Mandate
+1. **Continuous Capture:** Agents MUST proactively update the files in `.agent/` (Design, UX, Standards, Mission, Preferences) as new decisions, patterns, or user preferences are revealed.
+2. **No Stale Instructions:** If a workflow or technical standard evolves, the agent is responsible for reflecting that change in the Master Rulebook immediately.
+3. **Worklog Integrity:** The `.agent/worklog.md` must be updated at the start and end of EVERY session to ensure continuity.
+
+## 3. Workflows
+
+### Research -> Strategy -> Execution
+1. **Research:** Map codebase, validate assumptions, reproduce bugs.
+2. **Strategy:** Share a summary. Wait for approval if significant.
+3. **Execution (Plan-Act-Validate):**
+ - **Plan:** Define implementation and testing.
+ - **Act:** Apply surgical, idiomatic changes.
+ - **Validate:** Run `go test ./...` and `npm run build`.
+
+## 4. Agent Context API (Snapshots)
+
+The project includes an internal API for agents to understand the current user's task and meal context.
+
+- **Request Access:** `POST /agent/auth/request` (returns `request_token`).
+- **Poll Status:** `GET /agent/auth/poll?token=<request_token>` (awaits browser approval).
+- **Get Context:** `GET /agent/context` (requires Bearer token).
+- **Snapshot Endpoint:** `GET /api/claude/snapshot` (legacy, see `internal/handlers/agent.go` for new unified flow).
+
+## 5. Essential Commands
+
+| Command | Action |
+|---------|--------|
+| `go run cmd/dashboard/main.go` | Start application |
+| `go test ./...` | Run all tests |
+| `./scripts/deploy` | Deploy to production |
+| `./scripts/logs` | View production logs |
+| `./scripts/bugs` | List open production bugs |
+| `./scripts/resolve-bug <id>` | Resolve a production bug |
diff --git a/.agent/design.md b/.agent/design.md
new file mode 100644
index 0000000..f7b55c8
--- /dev/null
+++ b/.agent/design.md
@@ -0,0 +1,831 @@
+# Task Dashboard - Design Document
+
+## Overview
+
+Task Dashboard is a personal productivity web application that aggregates tasks, meals, calendar events, and shopping lists from multiple external services into a unified, mobile-friendly interface. Built with Go backend, HTMX frontend, Tailwind CSS styling, and SQLite storage.
+
+**Stack:** Go 1.24 | chi router | HTMX 1.x | Tailwind CSS | SQLite (WAL mode)
+
+---
+
+## Project Intent
+
+The dashboard serves as a **personal consolidation hub** designed to:
+
+1. **Aggregate multiple data sources** into one view (Trello, Todoist, PlanToEat, Google Calendar, Google Tasks, user-reported bugs)
+2. **Prioritize reliability** over speed - graceful degradation when APIs fail
+3. **Support mobile-first usage** - optimized for phone/tablet in-store or on-the-go
+4. **Minimize context switching** - complete tasks from any source without opening multiple apps
+5. **Provide live monitoring** - volcano webcams and weather for Hawaii location
+
+---
+
+## Architecture
+
+### Directory Structure
+
+```
+task-dashboard/
+├── cmd/dashboard/
+│ └── main.go # Entry point, route registration, ldflags
+├── internal/
+│ ├── api/ # External API clients
+│ │ ├── interfaces.go # API client contracts (interfaces)
+│ │ ├── http.go # BaseClient HTTP utilities
+│ │ ├── trello.go # Trello API client
+│ │ ├── todoist.go # Todoist API (REST v2 + Sync v9)
+│ │ ├── plantoeat.go # PlanToEat web scraper
+│ │ ├── google_calendar.go # Google Calendar integration
+│ │ └── google_tasks.go # Google Tasks integration
+│ ├── auth/
+│ │ ├── auth.go # Authentication service (bcrypt + WebAuthn)
+│ │ ├── handlers.go # Login/logout/passkey handlers
+│ │ └── middleware.go # Session + CSRF protection
+│ ├── config/
+│ │ ├── config.go # Environment configuration
+│ │ ├── constants.go # App constants (timeouts, limits)
+│ │ └── timezone.go # Display timezone helpers
+│ ├── handlers/
+│ │ ├── handlers.go # Main HTTP handlers + aggregation
+│ │ ├── settings.go # Settings page handlers
+│ │ ├── shopping.go # Shopping tab + mode handlers
+│ │ ├── agent.go # Agent auth + context API
+│ │ ├── websocket.go # WebSocket notification hub
+│ │ ├── timeline.go # Timeline view handler
+│ │ ├── timeline_logic.go # Timeline data processing
+│ │ ├── atoms.go # Unified task aggregation
+│ │ ├── cache.go # Generic cache fetcher pattern
+│ │ ├── helpers.go # Form parsing helpers
+│ │ ├── renderer.go # Template renderer interface
+│ │ └── response.go # JSON/HTML response utilities
+│ ├── middleware/
+│ │ └── security.go # Security headers + rate limiting
+│ ├── models/
+│ │ ├── types.go # Data models (Task, Card, Meal, Agent, etc.)
+│ │ ├── atom.go # Unified Atom model + converters
+│ │ └── timeline.go # TimelineItem + DaySection models
+│ └── store/
+│ └── sqlite.go # SQLite database layer
+├── migrations/ # SQL migration files (001-014)
+├── scripts/
+│ ├── bugs # List bugs from production DB (local)
+│ ├── deploy # Build + local deploy to /site
+│ ├── logs # Fetch production journalctl (local)
+│ └── resolve-bug # Resolve a production bug (local)
+├── web/
+```
+
+### Request Flow
+
+```
+Browser (HTMX request)
+ ↓
+chi Router (middleware stack)
+ ├── Logger, Recoverer, Timeout
+ ├── SecurityHeaders
+ ├── Session (LoadAndSave)
+ └── CSRFProtect
+ ↓
+Handler Function
+ ├── API Client (fetch from external service)
+ │ └── BaseClient.Get/Post (HTTP with context)
+ └── Store (SQLite cache)
+ └── Get*/Save* methods
+ ↓
+Template Rendering
+ ├── Full page: ExecuteTemplate(w, "filename.html", data)
+ └── Partial: ExecuteTemplate(w, "partial-name", data)
+ ↓
+HTML Response → HTMX swap
+```
+
+### Data Flow Patterns
+
+**Cache-First with Fallback:**
+```go
+// internal/handlers/cache.go pattern
+1. Check IsCacheValid(key) - TTL-based
+2. If valid, return cached data from SQLite
+3. If expired, fetch from API
+4. If API fails, return stale cache (graceful degradation)
+5. On success, save to cache + update metadata
+```
+
+**Unified Atom Model:**
+```go
+// internal/models/atom.go
+// Normalizes Todoist tasks, Trello cards, bugs → single Atom struct
+TaskToAtom(Task) → Atom{Source: "todoist", SourceIcon: "🔴", ...}
+CardToAtom(Card) → Atom{Source: "trello", SourceIcon: "📋", ...}
+BugToAtom(Bug) → Atom{Source: "bug", SourceIcon: "🐛", ...}
+```
+
+**Timeline Aggregation:**
+```go
+// internal/handlers/timeline_logic.go
+BuildTimeline(ctx, store, calendarClient, tasksClient, start, end)
+├── Fetch tasks with due dates (Todoist)
+├── Fetch cards with due dates (Trello)
+├── Fetch meals (PlanToEat) → apply default times
+├── Fetch events (Google Calendar)
+├── Fetch tasks (Google Tasks)
+├── Convert all to TimelineItem
+├── Compute DaySection (today/tomorrow/later)
+└── Sort by Time
+```
+
+---
+
+## Visual Design
+
+### Color Palette
+
+| Usage | Value | Tailwind |
+|-------|-------|----------|
+| Panel background | `rgba(0,0,0,0.4)` | `bg-black/40` |
+| Card background | `rgba(0,0,0,0.5)` | `bg-black/50` |
+| Card hover | `rgba(0,0,0,0.6)` | `bg-black/60` |
+| Primary text | `#ffffff` | `text-white` |
+| Secondary text | `rgba(255,255,255,0.7)` | `text-white/70` |
+| Muted text | `rgba(255,255,255,0.5)` | `text-white/50` |
+| Border subtle | `rgba(255,255,255,0.1)` | `border-white/10` |
+| Border accent | `rgba(255,255,255,0.2)` | `border-white/20` |
+| Todoist accent | `#e44332` | `border-red-500` |
+| Trello accent | `#0079bf` | `border-blue-500` |
+| PlanToEat accent | `#10b981` | `border-green-500` |
+
+### Component Patterns
+
+**Card Container:**
+```html
+<div class="bg-card bg-card-hover transition-colors rounded-lg border border-white/5">
+ <div class="flex items-start gap-3 p-3">
+ <!-- checkbox → icon → content → link -->
+ </div>
+</div>
+```
+
+**Tab Button:**
+```html
+<button class="tab-button {{if .IsActive}}tab-button-active{{end}}">
+ <span>🗓️</span> Timeline
+</button>
+```
+
+**Badge:**
+```html
+<span class="text-xs px-2 py-0.5 rounded bg-blue-900/50 text-blue-300">
+ trello
+</span>
+```
+
+**Glass Morphism:**
+- `bg-black/40 backdrop-blur-sm` for panels
+- `bg-black/60 backdrop-blur-lg` for modals
+- `box-shadow: 0 0 12px black` for depth
+
+**Z-Index Hierarchy:**
+| Layer | z-index | Element |
+|-------|---------|---------|
+| Content | default | Page content |
+| Sticky headers | z-10 | Timeline section headers |
+| FAB button | z-50 | Floating action button |
+| Modals | z-50 | Action modal, edit modal |
+| Dropdowns/Popups | z-100 | Navigation dropdown, context menus |
+
+### Typography
+
+- **Font:** Inter (300, 400, 500, 600 weights)
+- **Headings:** `font-light tracking-wide text-white`
+- **Labels:** `text-xs font-medium tracking-wider uppercase`
+- **Body:** `text-sm text-white/70`
+
+### Quick Add UX Pattern
+
+All quick-add forms (shopping, tasks, etc.) must follow these behaviors for rapid data entry:
+
+**On Successful Submission:**
+1. **Clear input** - Reset the form/input field immediately
+2. **Refocus input** - Return focus to the text input for the next entry
+3. **Visual feedback** - Brief flash (green background, 300ms) to confirm success
+4. **Update list** - New item appears in the list immediately
+
+**On Error:**
+1. **Preserve input** - Do not clear the input so user can retry
+2. **Show error** - Display error message near the input
+3. **Maintain focus** - Keep focus on the input
+
+**Checked/Completed Items:**
+- Completed items are immediately removed from view (not just crossed out)
+- User items: Deleted from database
+- External items (Trello, PlanToEat): Marked as checked, filtered from display
+
+---
+
+## API Integrations
+
+### Summary Table
+
+| Service | Auth Method | Config Var | Read | Write | Notes |
+|---------|-------------|------------|------|-------|-------|
+| Todoist | Bearer token | `TODOIST_API_KEY` | ✓ Tasks, Projects | ✓ Create, Complete | Incremental sync available |
+| Trello | Key + Token | `TRELLO_API_KEY`, `TRELLO_TOKEN` | ✓ Boards, Cards, Lists | ✓ Create, Archive | Concurrent board fetching |
+| PlanToEat | Session cookie | `PLANTOEAT_SESSION` | ✓ Meals, Shopping | ✗ | Web scraping (brittle) |
+| Google Calendar | OAuth file | `GOOGLE_CREDENTIALS_FILE` | ✓ Events | ✗ | Multi-calendar support |
+| Google Tasks | OAuth file | `GOOGLE_CREDENTIALS_FILE` | ✓ Tasks | ✓ Complete | Shared credentials with Calendar |
+
+### Interface Pattern
+
+All API clients implement interfaces (in `internal/api/interfaces.go`):
+
+```go
+type TodoistAPI interface {
+ GetTasks(ctx context.Context) ([]models.Task, error)
+ GetProjects(ctx context.Context) ([]models.Project, error)
+ CreateTask(ctx context.Context, content, projectID string, dueDate *time.Time, priority int) (*models.Task, error)
+ CompleteTask(ctx context.Context, taskID string) error
+ ReopenTask(ctx context.Context, taskID string) error
+ // ...
+}
+```
+
+Compile-time enforcement:
+```go
+var _ TodoistAPI = (*TodoistClient)(nil)
+```
+
+### Timezone Handling
+
+All times normalized to display timezone:
+```go
+config.SetDisplayTimezone("Pacific/Honolulu") // Set at startup
+config.Now() // Current time in display TZ
+config.Today() // Current date in display TZ
+config.ToDisplayTZ(t) // Convert any time
+config.ParseDateInDisplayTZ("2026-01-27") // Parse in display TZ
+```
+
+---
+
+## Features
+
+### Timeline View (`/tabs/timeline`)
+
+Chronological view of all upcoming items grouped by day section.
+
+**Data Sources:** Todoist, Trello, PlanToEat, Google Calendar, Google Tasks
+
+**Organization:**
+- **Today** (expanded, collapsible) - Items due today
+- **Tomorrow** (expanded, collapsible) - Items due tomorrow
+- **Later** (collapsed) - Items 2+ days out
+
+**Item Display:**
+- Color-coded dot (blue=event, orange=meal, green=task, yellow=gtask)
+- Time display (hidden for all-day items at midnight)
+- Checkbox for completable items
+- Title + description (2-line clamp)
+- External link icon
+
+### Tasks View (`/tabs/tasks`)
+
+Unified task grid showing Atoms (normalized tasks from all sources).
+
+**Layout:** 3-column responsive grid
+
+**Features:**
+- Priority sorting (overdue → today → future → no date)
+- Source icons (🔴 Todoist, 📋 Trello, 🐛 Bug)
+- Expandable descriptions
+- Collapsible "Future" section
+
+### Shopping View (`/tabs/shopping`)
+
+Aggregated shopping lists from Trello + PlanToEat + user items.
+
+**Tab Mode:** Store sections with items, quick-add form
+
+**Shopping Mode (`/shopping/mode/{store}`):** Full-screen mobile-optimized view
+- Store switcher (horizontal tabs)
+- Large touch targets
+- Fixed bottom quick-add
+
+### Meals View (`/tabs/meals`)
+
+PlanToEat meal schedule for the next 7 days.
+
+**Features:**
+- Meals grouped by date + meal type (breakfast/lunch/dinner)
+- Multiple recipes for same slot combined with " + " separator
+- Sorted by date, then meal type order
+
+### Conditions Page (`/conditions`)
+
+**Public route** - no authentication required.
+
+Standalone live feeds page with:
+- 3 Kilauea volcano webcams (USGS)
+- 2 Hawaii weather maps (Windy.com)
+- 1 National weather map
+
+Auto-refresh webcam images every 60 seconds.
+
+### Agent Context API (`/agent/*`)
+
+External agent authentication and data access system. Allows CLI tools, automation scripts, and AI assistants to access dashboard context securely.
+
+**Authentication Flow:**
+1. Agent sends `POST /agent/auth/request` with name + agent_id (UUID)
+2. Dashboard checks trust level:
+ - **TRUSTED**: Auto-approve if agent_id was previously approved
+ - **UNKNOWN**: Send WebSocket notification to connected browsers
+ - **BLOCKED**: Reject immediately
+3. User approves/denies via modal in browser (pushed via WebSocket)
+4. Agent polls `GET /agent/auth/poll?token=REQUEST_TOKEN` for result
+5. On approval, agent receives session_token (1-hour TTL)
+6. Agent uses session_token in Authorization header for context access
+
+**Endpoints:**
+
+| Method | Path | Auth | Purpose |
+|--------|------|------|---------|
+| POST | `/agent/auth/request` | None | Request access (returns request_token) |
+| GET | `/agent/auth/poll` | None | Poll for approval status |
+| POST | `/agent/auth/approve` | Browser session | User approves agent request |
+| POST | `/agent/auth/deny` | Browser session | User denies agent request |
+| GET | `/agent/context` | Agent session | Full timeline context (7 days back, 14 forward) |
+| GET | `/agent/web/request` | None | HTML auth flow for browser-only agents |
+| GET | `/agent/web/status` | None | HTML status page |
+| GET | `/agent/web/context` | None | HTML context view |
+
+**WebSocket Notifications (`/ws/notifications`):**
+- Pushes agent auth requests to connected browsers in real-time
+- JSON protocol with auto-reconnect on disconnect
+- Frontend handler in `web/static/js/app.js`
+
+**Security:**
+- Rate limit: 10 requests/minute per IP on auth endpoints
+- Session TTL: 1 hour, one active session per agent_id
+- Impersonation detection: Rejects if name/agent_id mismatch previous binding
+
+**Implementation:** `internal/handlers/agent.go`, `internal/handlers/websocket.go`
+
+### Completed Tasks Log
+
+Tracks task completion history for audit trail and agent context.
+
+**Purpose:**
+- Provides completion history in agent context API
+- Enables future analytics/reporting
+- Audit trail of completed work
+
+**Storage:** `completed_tasks` table (source, source_id, title, due_date, completed_at)
+
+**Feature Toggle:** `completed_log` (enabled by default)
+
+**Populated by:** `HandleCompleteAtom()` on task/card completion
+
+---
+
+## Database Schema
+
+**Engine:** SQLite with WAL mode (concurrent reads)
+
+**Key Tables:**
+
+| Table | Purpose | Key Columns |
+|-------|---------|-------------|
+| `tasks` | Todoist cache | id, content, due_date, priority, completed |
+| `boards` | Trello boards | id, name |
+| `cards` | Trello cards | id, name, board_id, list_id, due_date |
+| `meals` | PlanToEat meals | id, recipe_name, date, meal_type |
+| `users` | Authentication | id, username, password_hash |
+| `sessions` | SCS sessions | token, data, expiry |
+| `bugs` | Bug reports | id, description, resolved_at |
+| `user_shopping_items` | User-added items | id, name, store, checked |
+| `shopping_item_checks` | External item state | source, item_id, checked |
+| `cache_metadata` | Cache timestamps | key, last_fetch, ttl_minutes |
+| `sync_tokens` | Incremental sync | service, token |
+| `agents` | Registered agents | name, agent_id, trust_level, last_seen |
+| `agent_sessions` | Agent auth sessions | agent_id, request_token, session_token, status, expires_at |
+| `completed_tasks` | Completion log | source, source_id, title, due_date, completed_at |
+| `feature_toggles` | Feature flags | name, description, enabled |
+| `source_config` | Source filtering | source, item_type, item_id, item_name, enabled |
+
+---
+
+## Development Guide for Claude Code
+
+### Getting Started
+
+1. **Read this file first** - Understand architecture and patterns
+2. **Check `CLAUDE.md`** - Project-specific instructions
+3. **Run tests before changes:** `go test ./...`
+4. **Run after changes:** `go test ./...` then `go build`
+
+### Key Principles
+
+1. **Cache-First, Fail-Soft:** Never hard-fail if an API is down. Return cached data.
+2. **Minimal Changes:** Surgical edits only. Don't refactor unrelated code.
+3. **Interface-Driven:** API clients implement interfaces for testability.
+4. **HTMX for Updates:** Use partials and `hx-swap` for reactive UI.
+
+### Common Patterns
+
+**Adding a new handler:**
+```go
+// internal/handlers/handlers.go
+func (h *Handler) HandleNewFeature(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ // 1. Parse input
+ if err := r.ParseForm(); err != nil {
+ JSONError(w, http.StatusBadRequest, "Parse failed", err)
+ return
+ }
+
+ // 2. Validate
+ value := r.FormValue("key")
+ if value == "" {
+ JSONError(w, http.StatusBadRequest, "Missing key", nil)
+ return
+ }
+
+ // 3. Business logic
+ result, err := h.apiClient.DoSomething(ctx, value)
+ if err != nil {
+ JSONError(w, http.StatusInternalServerError, "Failed", err)
+ return
+ }
+
+ // 4. Save to cache (best-effort)
+ _ = h.store.SaveResult(result)
+
+ // 5. Respond
+ HTMLResponse(w, h.renderer, "partial-name", result)
+}
+```
+
+**Adding a new API method:**
+```go
+// 1. Add to interface (internal/api/interfaces.go)
+type MyAPI interface {
+ NewMethod(ctx context.Context, param string) (Result, error)
+}
+
+// 2. Implement in client (internal/api/myclient.go)
+func (c *MyClient) NewMethod(ctx context.Context, param string) (Result, error) {
+ var result Result
+ if err := c.Get(ctx, "/endpoint/"+param, c.authHeaders(), &result); err != nil {
+ return Result{}, fmt.Errorf("failed to fetch: %w", err)
+ }
+ return result, nil
+}
+```
+
+**Adding a new template:**
+```html
+<!-- web/templates/partials/new-feature.html -->
+{{define "new-feature"}}
+<div class="space-y-4">
+ {{range .Items}}
+ <div class="bg-card rounded-lg p-4">
+ <h3 class="text-white font-medium">{{.Title}}</h3>
+ </div>
+ {{end}}
+</div>
+{{end}}
+```
+
+**Adding a new route:**
+```go
+// cmd/dashboard/main.go inside protected routes group
+r.Get("/tabs/newfeature", h.HandleNewFeature)
+r.Post("/newfeature/action", h.HandleNewAction)
+```
+
+### Template Naming Convention
+
+| Type | Location | Reference |
+|------|----------|-----------|
+| Standalone page | `web/templates/name.html` | `"name.html"` |
+| Partial | `web/templates/partials/name.html` | `"name"` (define name) |
+
+**Example:**
+```go
+// Standalone page - use filename
+h.renderer.Render(w, "shopping-mode.html", data)
+
+// Partial - use define name
+HTMLResponse(w, h.renderer, "shopping-tab", data)
+```
+
+### HTMX Patterns
+
+**Tab content loading:**
+```html
+<div id="tab-content"
+ hx-get="/tabs/{{.ActiveTab}}"
+ hx-trigger="load"
+ hx-swap="innerHTML">
+</div>
+```
+
+**Form submission with swap:**
+```html
+<form hx-post="/complete-atom"
+ hx-vals='{"id": "{{.ID}}", "source": "{{.Source}}"}'
+ hx-target="closest div.rounded-lg"
+ hx-swap="outerHTML">
+```
+
+**Refresh trigger:**
+```javascript
+// After action completes
+htmx.trigger(document.body, 'refresh-tasks')
+```
+
+### Test Patterns
+
+**Unit test for store:**
+```go
+func TestStore_SaveTasks(t *testing.T) {
+ db := setupTestStore(t)
+ defer db.Close()
+
+ tasks := []models.Task{{ID: "1", Content: "Test"}}
+ err := db.SaveTasks(tasks)
+ require.NoError(t, err)
+
+ result, err := db.GetTasks()
+ require.NoError(t, err)
+ assert.Len(t, result, 1)
+}
+```
+
+**Handler test:**
+```go
+func TestHandler_HandleDashboard(t *testing.T) {
+ h := setupTestHandler(t)
+
+ req := httptest.NewRequest(http.MethodGet, "/", nil)
+ w := httptest.NewRecorder()
+
+ h.HandleDashboard(w, req)
+
+ assert.Equal(t, http.StatusOK, w.Code)
+}
+```
+
+### Debugging Tips
+
+1. **Production logs:** `bash scripts/logs -n 200 2>&1 | grep -i error`
+2. **Production bugs:** `bash scripts/bugs` to list, `bash scripts/resolve-bug <id>` to close
+3. **Cache issues:** Check `cache_metadata` table for stale timestamps
+4. **API failures:** Look for `"Warning:"` or `"ERROR:"` prefixes in logs
+5. **Template errors:** Check for `html/template: "name" is undefined`
+6. **HTMX issues:** Browser DevTools Network tab shows all requests
+7. **WebAuthn issues:** Check for "WebAuthn initialized" in startup logs; requires `WEBAUTHN_RP_ID` + `WEBAUTHN_ORIGIN` env vars
+
+### Files You'll Modify Most
+
+| Task | Primary Files |
+|------|--------------|
+| New feature | `handlers.go` or new handler file, `main.go`, new template |
+| Bug fix | Relevant handler file or API client |
+| UI change | Template in `partials/`, maybe `input.css` |
+| API integration | New file in `internal/api/`, update `interfaces.go` |
+| Database change | New migration in `migrations/`, update `sqlite.go` |
+| Settings | `settings.go`, `settings.html` |
+| Shopping | `shopping.go`, `shopping-tab.html` or `shopping-mode.html` |
+
+### Common Mistakes to Avoid
+
+1. **Don't use `"name"` for standalone pages** - Use `"name.html"`
+2. **Don't forget context propagation** - All handlers should use `r.Context()`
+3. **Don't panic on API errors** - Return cached data or empty slice
+4. **Don't modify tests without running them** - `go test ./...`
+5. **Don't add unnecessary comments** - Code should be self-explanatory
+6. **Don't create new files unless necessary** - Prefer editing existing
+7. **Don't refactor working code** - Only touch what's needed
+
+### Feature Toggles
+
+Feature toggles allow gradual rollout of new features and easy rollback if issues arise.
+
+**When to use feature toggles:**
+- New features that may need adjustment after deployment
+- Experimental features being tested
+- Features that depend on external services that may be unreliable
+- Any change that could break existing functionality
+
+**Creating a feature toggle:**
+
+1. Add a migration or use the Settings UI at `/settings`
+2. Check the toggle in your handler:
+```go
+if h.store.IsFeatureEnabled("my_feature") {
+ // New behavior
+} else {
+ // Old behavior or disabled state
+}
+```
+
+3. Document the toggle in this file under "Active Feature Toggles"
+
+**Managing feature toggles:**
+- Access the Settings page at `/settings` to view/toggle/create features
+- Store methods: `IsFeatureEnabled()`, `SetFeatureEnabled()`, `CreateFeatureToggle()`
+- Toggles are stored in the `feature_toggles` table
+
+**Lifecycle:**
+1. **Create** toggle (disabled by default) before deploying feature
+2. **Enable** after deployment if tests pass
+3. **Monitor** for issues
+4. **Remove** toggle and conditional code once feature is stable (usually after 1-2 weeks)
+
+**Active Feature Toggles:**
+| Name | Description | Status |
+|------|-------------|--------|
+| `source_config` | Configure which boards/lists/calendars to fetch | Disabled |
+| `calendar_timeline` | Show timeline as a calendar view with time slots | Disabled |
+| `completed_log` | Track and display completed tasks log | Enabled |
+
+### Bug Management Workflow
+
+Use the bug tracking system to report and resolve issues:
+
+**Viewing bugs (production):**
+```bash
+./scripts/bugs
+# Lists all bugs from production database with ID, description, and created_at
+```
+
+**Resolving a bug:**
+```bash
+./scripts/resolve-bug <bug_id>
+# Shows bug description, then deletes it from the database
+```
+
+**Workflow:**
+1. Bugs are reported via the dashboard UI (🐛 tab in quick-add modal)
+2. Run `./scripts/bugs` to see current issues
+3. Fix the bug with tests
+4. Deploy the fix
+5. Run `./scripts/resolve-bug <id>` to close it
+
+Bugs appear as atoms in the Tasks view (🐛 icon) until resolved.
+
+### Test Locations & Commands
+
+**Test locations:**
+| Component | Test File |
+|-----------|-----------|
+| Store methods | `internal/store/sqlite_test.go` |
+| Handlers | `internal/handlers/handlers_test.go` |
+| Timeline logic | `internal/handlers/timeline_logic_test.go` |
+| Agent handlers | `internal/handlers/agent_test.go` |
+| API clients | `internal/api/*_test.go` |
+| Auth | `internal/auth/*_test.go` |
+| Integration | `test/acceptance_test.go` |
+
+**Running tests:**
+```bash
+# All tests
+go test ./...
+
+# Specific package
+go test ./internal/handlers/...
+
+# Verbose with coverage
+go test -v -cover ./...
+
+# Single test
+go test -run TestBuildTimeline ./internal/handlers/...
+```
+
+**Test patterns:**
+```go
+func TestFeature_Behavior(t *testing.T) {
+ // Arrange
+ db := setupTestStore(t)
+ defer db.Close()
+
+ // Act
+ result, err := db.SomeMethod(input)
+
+ // Assert
+ require.NoError(t, err)
+ assert.Equal(t, expected, result)
+}
+```
+
+### Architecture Decision Records
+
+**Current ADRs:**
+| ADR | Decision |
+|-----|----------|
+| 001 | Session-based authentication with SQLite storage |
+| 002 | Polymorphic TimelineItem model for unified aggregation |
+| 003 | HTMX partials for all write operations |
+| 004 | Concurrent fetching with semaphore + cache fallback |
+| 005 | Agent API notification-based authentication |
+
+**ADR template:**
+```markdown
+# ADR NNN: Title
+
+## Status
+Proposed | Accepted | Deprecated | Superseded
+
+## Context
+What is the issue or decision we need to make?
+
+## Decision
+What did we decide and why?
+
+### Technical Details:
+- Implementation specifics
+- Key code locations
+
+## Consequences
+- **Pros:** Benefits of this approach
+- **Cons:** Tradeoffs and limitations
+
+## Alternatives Considered
+- Option A: Why rejected
+- Option B: Why rejected
+```
+
+**Numbering:** Use sequential 3-digit numbers (001, 002, etc.)
+
+---
+
+## Quick Reference
+
+### Commands
+
+```bash
+# Run application
+go run cmd/dashboard/main.go
+
+# Run tests
+go test ./...
+
+# Build binary
+go build -o dashboard cmd/dashboard/main.go
+
+# Rebuild Tailwind CSS
+npx tailwindcss -i web/static/css/input.css -o web/static/css/output.css --watch
+```
+
+### Key Endpoints
+
+| Method | Path | Purpose |
+|--------|------|---------|
+| GET | `/` | Main dashboard |
+| GET | `/tabs/timeline` | Timeline partial |
+| GET | `/tabs/tasks` | Tasks partial |
+| GET | `/tabs/planning` | Planning partial |
+| GET | `/tabs/meals` | Meals partial |
+| GET | `/tabs/shopping` | Shopping partial |
+| GET | `/tabs/conditions` | Conditions partial |
+| GET | `/conditions` | Live feeds page (public) |
+| POST | `/complete-atom` | Complete task/card/bug |
+| POST | `/uncomplete-atom` | Reopen task/card |
+| POST | `/unified-add` | Quick add task |
+| GET | `/bugs` | List bug reports |
+| POST | `/bugs` | Submit bug report |
+| POST | `/shopping/add` | Add shopping item |
+| GET | `/shopping/mode/{store}` | Shopping mode view |
+| POST | `/shopping/mode/{store}/toggle` | Toggle shopping item |
+| POST | `/shopping/mode/{store}/complete` | Complete shopping item |
+| GET | `/settings` | Settings page |
+| POST | `/settings/features` | Create feature toggle |
+| POST | `/settings/features/toggle` | Toggle feature on/off |
+| GET | `/settings/passkeys` | List passkeys (requires WebAuthn) |
+| POST | `/passkeys/register/begin` | Start passkey registration |
+| POST | `/passkeys/register/finish` | Complete passkey registration |
+| GET | `/ws/notifications` | WebSocket for agent notifications |
+| POST | `/agent/auth/request` | Agent requests access |
+| GET | `/agent/auth/poll` | Agent polls for approval |
+| POST | `/agent/auth/approve` | User approves agent |
+| GET | `/agent/context` | Agent gets timeline context |
+
+### Handler Signature
+
+```go
+func (h *Handler) HandleName(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+ // ... implementation
+}
+```
+
+### Response Helpers
+
+```go
+JSONResponse(w, data) // 200 + JSON + no-cache
+JSONError(w, status, "message", err) // Error + log
+HTMLResponse(w, h.renderer, "name", data) // Partial render + no-cache
+HTMLString(w, "<html>...</html>") // Raw HTML
+```
diff --git a/.agent/mission.md b/.agent/mission.md
new file mode 100644
index 0000000..64575e5
--- /dev/null
+++ b/.agent/mission.md
@@ -0,0 +1,16 @@
+# Project Mission & Strategic Values
+
+## 1. Core Mission
+**Unified Situational Awareness.** Doot is the single "lens" through which the user views their entire digital life. It is not a replacement for the source tools (Trello, Todoist), but a high-speed aggregation layer for clarity.
+
+## 2. Strategic Values
+- **Simplicity over Complexity:** If a feature makes the dashboard harder to read at a glance, it doesn't belong.
+- **Glanceable Information:** The UI is designed for "5-second updates," not "5-minute deep dives."
+- **Resilience is Mandatory:** Never show an error spinner where stale/cached data could be shown instead. The dashboard must be "always on."
+- **Mobile-First Utility:** The primary use case is "checking the plan" while on the move or in the kitchen (meals/shopping).
+
+## 3. Agent Personality & Role
+- **The Proactive Chief of Staff:** Agents should anticipate gaps and propose solutions, but always remain within safety guardrails.
+- **Continuous Clarification:** A "GO" (Directive) is a permission to implement, but it is NOT a mandate to stop asking questions. If a sub-task is ambiguous or an unexpected edge case is found during execution, the agent MUST stop and clarify with the user before proceeding.
+- **High-Signal, Low-Noise:** Communication should be professional, technical, and concise.
+- **Surgical Execution:** Changes should be minimal and idiomatic.
diff --git a/.agent/narrative.md b/.agent/narrative.md
new file mode 100644
index 0000000..778df85
--- /dev/null
+++ b/.agent/narrative.md
@@ -0,0 +1,32 @@
+# Engineering Narrative & Project Evolution
+
+This document tracks the chronological history and major milestones of the **Doot** ecosystem (including its relationship with Claudomator).
+
+## 1. Ecosystem Origins (Claudomator)
+**Claudomator** was developed as the core "task-execution engine." It introduced:
+- **Human-in-the-Loop Workflow:** A `READY` state that requires operator sign-off (`Accept/Reject`) before a task is considered `COMPLETED`.
+- **Question/Answer Flow:** Agents can transition a task to `BLOCKED` by writing a `question.json` file, allowing users to provide context asynchronously.
+- **Subtask Graphing:** The `claudomator` CLI allows agents to break complex goals into manageable subtasks.
+
+## 2. The Birth of Doot (Consolidation)
+**Doot** (this project) was created to solve "Context Blindness." Instead of managing tasks across Todoist, Trello, and Google Calendar separately, Doot aggregates them into a single, high-speed interface.
+
+### Key Milestones:
+- **Phase 1: Read-Only Aggregation:** Initial dashboard with Trello, Todoist, and PlanToEat.
+- **Phase 2: Authentication:** Wired up `internal/auth` with SQLite sessions and default admin user.
+- **Phase 3: Timeline & Google Integration:** Added the "Timeline" view, aggregating Google Calendar and Google Tasks via a cached store layer.
+- **Phase 4: Agent Context API:** Built the `/agent/context` endpoint and WebSocket-based approval flow to let AI agents "see" what the user is working on safely.
+
+## 3. Current Direction: Strategic Execution
+The project is currently evolving into a **Strategic Agent Studio**, where:
+- Doot serves as the "Lens" (View/Approve).
+- Claudomator serves as the "Muscle" (Execute/Deliver).
+- The `.agent/` directory serves as the "Brain" (Config/Context).
+
+## 4. Historical Activity Log (Raw)
+
+--- 2026-03-16T01:52:44Z ---
+Do a thorough review for refactoring opportunities, logic bugs and code, redundancy and shaky abstractions. Create claudomator tasks for each
+
+--- 2026-03-17T09:02:26Z ---
+Completing Trello tasks doesn't work: failed to load content (Fix: Verified and corrected Trello API param mapping)
diff --git a/.agent/preferences.md b/.agent/preferences.md
new file mode 100644
index 0000000..4d79ba2
--- /dev/null
+++ b/.agent/preferences.md
@@ -0,0 +1,15 @@
+# User Preferences & Workflow Quirks
+
+This file is a "living record" of the user's personal preferences, discovered patterns, and workflow expectations. Agents must proactively update this file as new preferences are revealed during interaction.
+
+## 1. Interaction & Workflow
+- **Safety First:** The user prefers caution and deliberate action.
+- **The "Checkpoint" Model:** Research first, strategy second, and wait for a "GO" (Directive).
+- **Continuous Clarification:** A "GO" is not a mandate to stop asking questions. If execution hits an ambiguity, stop and ask.
+- **Living Docs:** Agents are empowered and expected to update any file in the `.agent/` directory when a new fact, decision, or preference is established.
+
+## 2. Technical Preferences
+- (To be populated as preferences are revealed during the project...)
+
+## 3. UI/UX Style
+- (To be populated as preferences are revealed during the project...)
diff --git a/.agent/timeline_design.md b/.agent/timeline_design.md
new file mode 100644
index 0000000..61c71b5
--- /dev/null
+++ b/.agent/timeline_design.md
@@ -0,0 +1,82 @@
+# Timeline Feature Design
+
+## Objective
+Create a unified timeline view showing Tasks, Meals, Trello Cards, and Google Calendar Events, sorted chronologically.
+
+## Data Sources
+1. **Tasks (Todoist):** From DB `tasks` table. Filter: `due_date` is not null.
+2. **Meals (PlanToEat):** From DB `meals` table. Filter: `date` is not null.
+3. **Cards (Trello):** From DB `cards` table. Filter: `due_date` is not null.
+4. **Google Calendar Events:** From `GoogleCalendarClient` (Live API).
+
+## Backend Logic
+
+### 1. Data Models (`internal/models/timeline.go`)
+We need a polymorphic structure to hold different item types.
+
+```go
+type TimelineItemType string
+
+const (
+ ItemTypeTask TimelineItemType = "task"
+ ItemTypeMeal TimelineItemType = "meal"
+ ItemTypeCard TimelineItemType = "card"
+ ItemTypeEvent TimelineItemType = "event"
+)
+
+type TimelineItem struct {
+ ID string `json:"id"`
+ Type TimelineItemType `json:"type"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Time time.Time `json:"time"`
+ AllDay bool `json:"all_day"`
+ URL string `json:"url"`
+ Meta map[string]any `json:"meta"` // Extra data like ProjectName, RecipeURL, etc.
+}
+```
+
+### 2. Store Extensions (`internal/store/`)
+Add methods to fetch items by date range.
+* `GetTasksByDateRange(start, end time.Time) ([]models.Task, error)`
+* `GetMealsByDateRange(start, end time.Time) ([]models.Meal, error)`
+* `GetCardsByDateRange(start, end time.Time) ([]models.Card, error)`
+
+### 3. Logic Layer (`internal/handlers/timeline_logic.go`)
+* **Function:** `BuildTimeline(store Store, calendarClient *api.GoogleCalendarClient, start, end time.Time) ([]TimelineItem, error)`
+* **Aggregation:**
+ 1. Fetch from Store (Tasks, Meals, Cards).
+ 2. Fetch from Calendar API.
+ 3. Convert all to `TimelineItem`.
+ 4. **Meal Time Defaults:**
+ * Breakfast: 08:00
+ * Lunch: 12:00
+ * Dinner: 19:00
+ * Other: 12:00
+ 5. Sort by `Time`.
+
+### 4. HTTP Handler (`internal/handlers/timeline.go`)
+* **Route:** `GET /timeline`
+* **Params:** `start` (default: today), `days` (default: 7)
+* **Response:** Render `timeline-tab.html` partial.
+
+## UI Design (`web/templates/partials/timeline-tab.html`)
+* **Structure:**
+ * Container
+ * Loop through Days
+ * Date Header (e.g., "Mon, Jan 2")
+ * List of Items
+ * Time Column (e.g., "14:00")
+ * Content Column (Icon + Title + Subtitle)
+* **Styling:**
+ * Use existing CSS variables.
+ * Distinct icons/colors for Tasks vs Meals vs Events.
+
+## Files to Modify
+1. `internal/models/timeline.go` (New)
+2. `internal/store/store.go` (Interface update)
+3. `internal/store/sqlite.go` (Implementation update)
+4. `internal/handlers/timeline_logic.go` (New)
+5. `internal/handlers/timeline.go` (New)
+6. `web/templates/partials/timeline-tab.html` (New)
+7. `cmd/dashboard/main.go` (Route registration)
diff --git a/.agent/ux_philosophy.md b/.agent/ux_philosophy.md
new file mode 100644
index 0000000..e9b6a87
--- /dev/null
+++ b/.agent/ux_philosophy.md
@@ -0,0 +1,82 @@
+# UI/UX Review & Redesign Proposal
+
+## Current State Analysis: "The Unusable Form"
+
+The current "Quick Add" modal (in `index.html`) and the "Planning" tab form suffer from several friction points:
+
+1. **Context Blindness:** When adding a Trello card, you must first pick a source, then a board, then a list. This is 3+ clicks before you even type the task name.
+2. **Repetitive Data Entry:** Creating multiple related stories (e.g., across 3 repos) requires filling the entire form 3 times.
+3. **No "Smart" Defaults:** The form doesn't remember your last used project, repo, or base image.
+4. **Mobile Friction:** Select dropdowns are native and small, making them hard to use for long lists of repos or boards.
+5. **Information Overload:** The "Task" and "Shopping" tabs in the modal use the same `HandleUnifiedAdd` endpoint but different fields, leading to a "leaky abstraction" in the UI.
+
+---
+
+## 1. Redesign: The "Command Palette" Model
+
+Instead of a traditional form, we should move towards a **Command Palette** style interaction (Ctrl+K).
+
+### Proposed Streamlined Flow:
+1. **Trigger:** `Ctrl+K` opens a search-first modal.
+2. **Type:** User types "doot: fix css in dashboard" or "claudomator: update go version".
+3. **Prefix Detection:**
+ * `d:` or `t:` -> Todoist task.
+ * `tr:` -> Trello card.
+ * `c:` or `s:` -> Claudomator Story (New).
+4. **Contextual Suggestions:** As the user types, the bottom of the modal shows:
+ * "Repo: doot" (detected from prefix or frequency)
+ * "Project: Phase 6"
+ * "Base Image: Go 1.24"
+
+---
+
+## 2. Resource Management Model (Repos, Images, Projects)
+
+The user requested a "better model for management." We should move away from flat strings and toward a **Resource Graph**.
+
+### New SQLite Schema (Internal)
+* **`claudomator_repos`:** `id, name, remote_url, default_branch, local_path`
+* **`claudomator_images`:** `id, name, tag, description (e.g., "Go 1.24 + Node 22")`
+* **`claudomator_projects`:** `id, name, description`
+* **`project_repos`:** Junction table linking projects to multiple repositories.
+
+### Management UI
+Instead of hiding these in settings, we should have a **"Library" view** (perhaps a new tab or a sub-section of Planning) where users can:
+* Quick-add a new repo.
+* Toggle which "Base Images" are active for selection.
+* Group repos into "Projects" for batch operations.
+
+---
+
+## 3. UI/UX Recommendations & Plugins
+
+### Recommended Plugins/Libraries
+1. **[Tom Select](https://tom-select.js.org/):** To replace native `<select>`. This allows for:
+ * Searchable dropdowns (essential for 20+ repos).
+ * Custom rendering (show repo icons/logos in the list).
+ * Remote data loading (HTMX-friendly).
+2. **[Alpine.js](https://alpinejs.dev/):** To handle "Local UI State" without page refreshes.
+ * Example: Toggling between "Simple Task" and "Complex Story" modes in the same modal.
+ * Example: Multi-select for repos.
+3. **[Tailwind Forms Plugin](https://github.com/tailwindlabs/tailwindcss-forms):** To make inputs look professional with zero effort.
+4. **[Lucide Icons](https://lucide.dev/):** To replace the emoji-heavy UI with cleaner, more professional SVG icons.
+
+---
+
+## 4. Proposed User Flow for Story Creation
+
+**Goal: From "Idea" to "Running Agent" in < 15 seconds.**
+
+1. **Open Studio:** User clicks a new "Create Story" button (or `Ctrl+K` then `s`).
+2. **Draft:** User types the goal.
+3. **Auto-Select:** System auto-selects the "Active Project" and its associated "Primary Repo".
+4. **Elaborate (AI):** User hits `Enter`. HTMX swaps the form for a "Thinking..." animation.
+5. **Review Tree:** AI returns a task tree. User can click a task to edit its "Validation Spec".
+6. **Launch:** User hits "Execute". Story moves to `IN_PROGRESS` and appears on the main dashboard.
+
+---
+
+## Next Steps (Deferred to Phase 7)
+* Implement the SQLite migrations for the new Resource Graph.
+* Build the "Story Studio" using Alpine.js + Tom Select.
+* Create the management UI for Repos and Projects.
diff --git a/.agent/worklog.md b/.agent/worklog.md
new file mode 100644
index 0000000..08f6409
--- /dev/null
+++ b/.agent/worklog.md
@@ -0,0 +1,81 @@
+# Session State
+
+## Current Focus
+Sync log + clear cache feedback
+
+## Recently Completed
+- **Sync log + clear cache feedback** — migration `016_sync_log.sql`, store methods `AddSyncLogEntry`/`GetRecentSyncLog`, handler changes, template partial `sync-log.html`
+ - `HandleClearCache` now renders sync log HTML (replaces `hx-swap="none"`)
+ - `HandleSyncSources` adds log entry after sync
+ - `HandleSettingsPage` passes `SyncLog []store.SyncLogEntry` to template
+ - Tests: `TestStore_AddAndGetSyncLog`, `TestStore_GetRecentSyncLog_LimitsResults`, `TestHandleClearCache_AddsLogEntry`, `TestHandleClearCache_ReturnsHTMLSyncLog`, `TestHandleSettingsPage_IncludesSyncLog`, `TestHandleSyncSources_AddsLogEntry`
+
+
+- **Bug 1: Todoist incremental sync** — added 5 tests exercising the incremental merge path (upsert, delete completed/deleted, sync token storage/reuse, forceRefresh). Code was already correct, just untested.
+ - Tests: `TestFetchTasks_IncrementalSync_UpsertsActiveTasks`, `TestFetchTasks_IncrementalSync_DeletesCompletedAndDeletedTasks`, `TestFetchTasks_IncrementalSync_StoresNewSyncToken`, `TestFetchTasks_IncrementalSync_UsesSavedSyncToken`, `TestFetchTasks_ForceRefresh_ClearsSyncToken`
+- **Bug 2: Task completion response/headers** — added assertions for response body (`rendered:completed-atom`), Content-Type header, HX-Reswap/HX-Trigger headers, template data verification. Code was correct, assertions were missing.
+ - Tests updated: `TestHandleCompleteAtom_Todoist`, `TestHandleUncompleteAtom_Todoist`
+ - New test: `TestHandleCompleteAtom_RendersCorrectTemplateData`
+- **Bug 3: Google Calendar cache layer** — calendar events now cached via `CacheFetcher` pattern, surviving API outages.
+ - New migration: `migrations/015_calendar_events.sql`
+ - New store methods: `SaveCalendarEvents`, `GetCalendarEvents`, `GetCalendarEventsByDateRange`
+ - New cache key: `store.CacheKeyGoogleCalendar`
+ - New handler method: `fetchCalendarEvents` (uses `CacheFetcher` with stale-cache fallback)
+ - `BuildTimeline` now reads events from store (removed `calendarClient` param)
+ - Tests: `TestBuildTimeline_ReadsCalendarEventsFromStore`, `TestFetchCalendarEvents_CacheFallbackOnAPIError`, `TestSaveAndGetCalendarEvents`
+- All tests pass (`go test ./...`)
+
+## Previously Completed
+- Extracted project-agnostic dev methodology to `~/.claude/CLAUDE.md`
+- Created `~/.claude/roles/` with architect.md, implementor.md, reviewer.md
+- Slimmed task-dashboard `CLAUDE.md` (87→72 lines, references global for methodology)
+- Trimmed `DESIGN.md` (removed Development Workflow, Git Practices, TDD methodology, ADR methodology, Config Reference duplication)
+- Deleted `ARCHITECT_ROLE.md`, `IMPLEMENTOR_ROLE.md`, `REVIEWER_ROLE.md` from repo
+
+## Previously Completed
+- Build version footer with ldflags injection (`deploy.sh`, `index.html`)
+- `assertTemplateContains` test helper, refactored existing template tests
+- `scripts/logs` for fetching production journalctl
+- Fix passkey registration: hide UI when WebAuthn not configured (WebAuthnEnabled flag)
+- Added no-cache header tests for #66
+
+## Completed Bugs (All Verified)
+- **#74**: Feature toggles — tests: `TestHandleToggleFeature`, `TestHandleCreateFeature`, `TestHandleDeleteFeature`; docs: DESIGN.md §4.3
+- **#56**: Box contents overflow — CSS-only fix, documented in DESIGN.md
+- **#65**: Google Tasks — timeline tests cover integration; API client lacks dedicated unit tests
+- **#66**: No-cache headers — tests: `TestHTMLResponse_SetsNoCacheHeaders`, `TestJSONResponse_SetsNoCacheHeaders`
+- **#67**: Z-index — CSS-only fix, documented in DESIGN.md §z-index hierarchy
+- **#68**: Track completion — tests: `TestHandleCompleteAtom_Todoist`, `TestHandleCompleteAtom_Trello`
+- **#69**: Timeline calendar — tests: `TestCalcCalendarBounds`, `TestBuildTimeline_IncludesOverdueItems`; docs: DESIGN.md §Timeline View
+- **#70**: Clear inputs — tests: `TestShoppingQuickAdd_Success`; docs: DESIGN.md §Quick Add UX
+- **#71**: Shopping checkmarks — tests: `TestShoppingModeItemsTemplateFiltersChecked`
+- **#72**: Inline add per store — tests: `TestShoppingQuickAdd_ShoppingModeReturnsStoreItems`
+- **#73**: Store grouping — partial tests, partial docs
+
+## Agent Context API
+- Status: [REVIEW_READY] Phase 1 Complete
+- Tests: `internal/handlers/agent_test.go` (comprehensive)
+- Docs: ADR-005, DESIGN.md §Agent Context API
+- Phase 2 (Write Operations) and Phase 3 (Create + Management) pending
+
+## Known Gaps
+- Google Tasks API client lacks dedicated unit tests (integration tested via timeline)
+- WebAuthn passkeys require `WEBAUTHN_RP_ID` and `WEBAUTHN_ORIGIN` env vars in production
+
+## Remaining Items (Feature Requests)
+- #12: Research task durations
+- #28: Bugs as first-class atoms
+- #30: Consistent background opacity
+- #31: PlanToEat ingredients
+- #33-38: Shopping/timeline features
+
+## Next Steps
+1. Set `WEBAUTHN_RP_ID` and `WEBAUTHN_ORIGIN` in production to enable passkeys
+2. **Phase 2**: Agent write operations (complete, uncomplete, update due date)
+3. **Phase 3**: Create task/shopping item, agent management UI
+
+## Process Improvements
+- Extracted dev workflow to `~/.claude/CLAUDE.md` — reusable across projects
+- Role definitions now in `~/.claude/roles/` — project-agnostic
+- CLAUDE.md reduced from 87 to 72 lines — faster to parse
+- DESIGN.md trimmed ~200 lines of duplicated methodology