ffdf70733f
feat: M2 AI tips — LiteLLM gateway, context assembler, end-to-end generation pipeline
...
Issues closed : #86 , #87 , #88 , #89 , #90 , #91 , #79 , #80 , #82
infra:
- docker-compose `ai` profile: Ollama + LiteLLM services
- infra/litellm/litellm_config.yaml: tip-generator / embedder / judge aliases
- .env.example: LITELLM_URL, LITELLM_MASTER_KEY, OLLAMA_URL
ml/serving:
- POST /generate: calls LiteLLM tip-generator alias, returns TipCandidate[]
- JSON retry loop (2 retries with correction prompt on malformed response)
- _parse_llm_json strips markdown fences
ml/features:
- context.py: build_context() assembles user signals → PromptContext
(sorts overdue/high-priority tasks first for LLM prompt quality)
shared-types:
- TipKind, TipSource, TipCandidate types
- Tip gains kind + rationale fields
services/api:
- recommender: 3-stage pipeline (assemble → score → serve)
Stage 1: Todoist tasks + LLM candidates fetched in parallel
Stage 2: egreedy bandit scores merged candidate pool
Stage 3: serve + log with prompt_version, llm_model, tip_kind
- tip_scores: prompt_version, llm_model, tip_kind columns + migrations
- config: LITELLM_URL added
- integrations: surface token_status in /integrations response
tests:
- ml/serving/tests/test_generate.py: 13 tests (retry, 502/503, fence variants)
- ml/features/test_context.py: 9 tests (sorting, edge cases)
- services/api recommender.unit.test.ts: 16 pure-function tests (inferReward, dueAgeDays)
- services/api recommender.test.ts: 4 integration tests (tip_scores columns, LLM fallback)
- shared-types: TipCandidate, rationale, full TipFeedback action set
docs:
- ADR-0008: LiteLLM AI gateway decision
- overview.md: M2 pipeline description updated
- ml/README.md: serving + features roles updated
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-17 14:09:02 +00:00
c7edd92e15
feat: M1 — LinUCB bandit, RemotePolicy, Web Push, event bus
...
ML serving:
- LinUCB contextual bandit (disjoint, d=5 features: hour_sin/cos, is_overdue, task_age, priority)
- /score endpoint replaces stub random; /reward endpoint for online learning
- Per-user model state persisted to disk as JSON (survives restarts)
- venv at ml/serving/.venv; start with pnpm dev from ml/serving
Recommender:
- Todoist fetch now extracts features (is_overdue, task_age_days, priority)
- RemotePolicy calls ml/serving with 3s timeout; falls back to RandomPolicy
- Reward sent to /reward on feedback (done=+1, snooze=0, dismiss=-1)
Web Push:
- VAPID keys in config; push_subscriptions table in DB
- POST/DELETE /api/push/subscribe; GET /api/push/vapid-public-key
- Service worker (public/sw.js): push → showNotification, notificationclick → focus/open
- "notify me" button on tip page; registers SW + subscribes on permission grant
Event bus:
- services/api/src/events/bus.ts: typed EventEmitter wrapper
- Subjects: signals.tip.served, signals.tip.feedback, signals.task.synced
- Same publish/subscribe API NATS JetStream will implement — swap is mechanical
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-15 14:08:00 +00:00
3123cb73fb
feat: Phase 0 walking skeleton — auth, Todoist integration, tip page
...
- Google OAuth2/PKCE flow via openid-client v6; session cookie (30-day)
- Next.js middleware auth guard — redirects before any client render
- Todoist OAuth2 connect/disconnect; REST v1 task fetch (today|overdue)
- RandomPolicy recommender behind stable POST /recommend contract
- Feedback endpoint (done/dismiss/snooze); marks task complete in Todoist
- 30s in-memory task cache per user (~1ms recommend on cache hit)
- Tip page: pure opacity fade-in (3.5s), fast fade-out (0.3s), no motion
- "reading you…" loading text with breathe animation
- PWA icons + manifest
- Ports pinned: API=3078, web=3079; Caddy at o.alogins.net
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-15 08:53:38 +00:00
65218762be
feat: Phase 0 walking skeleton — monorepo, API, web, ML stub
...
Sets up the full Phase 0 foundation:
- pnpm workspaces + turbo build graph; native module build approval
- packages/shared-types: HTTP contracts (Tip, Auth, Integrations, User)
- services/api: Express modular monolith with better-sqlite3/drizzle
- auth: Google OAuth2 + PKCE via openid-client v6, cookie sessions
- integrations: Todoist OAuth2 connect/disconnect, token vault
- recommender: RandomPolicy over Todoist tasks, feedback sink
- user: profile, consent capture, full account deletion (GDPR)
- apps/web: Next.js 15, three pages (sign-in → connect → tip)
- tip page: black canvas, hold-to-act gesture, action sheet
- PWA manifest + theme
- ml/serving: FastAPI stub implementing the POST /score contract
- infra: docker-compose (core/full profiles), Dockerfiles, CI skeleton
- .env.example with all required vars documented
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-14 12:41:24 +00:00