summaryrefslogtreecommitdiff
path: root/DESIGN.md
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-03-22 23:45:19 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-03-22 23:45:19 +0000
commit8abc63efdbc0bb96cd6c9aa99d6e9166e0bcabae (patch)
treef4d6a082eed9b10bc67436a3ca5188e0182961eb /DESIGN.md
parent11b905fd437d651b2e39745aa82a5dd36f70331e (diff)
chore: unify and centralize agent configuration in .agent/
Diffstat (limited to 'DESIGN.md')
-rw-r--r--DESIGN.md831
1 files changed, 0 insertions, 831 deletions
diff --git a/DESIGN.md b/DESIGN.md
deleted file mode 100644
index f7b55c8..0000000
--- a/DESIGN.md
+++ /dev/null
@@ -1,831 +0,0 @@
-# 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
-```