Block a user
feat: prompt versioning — track prompt_version + model in tip_scores
feat: LLM output validation + structured JSON retry for tip generation
feat: TipCandidate shared schema — typed candidates through the bandit pipeline
feat: context assembler — user signals → structured LLM prompt context
feat: AI gateway — wire ml/serving to LiteLLM with model aliases
infra:
ai compose profile — Ollama + LiteLLM for local dev
Consolidate MLflow + Airflow auth into shared OIDC provider
feat: tip kind system — task, advice, insight, reminder
feat: feature registry + user profile builder
research: next-gen ranking policies — Thompson sampling, neural bandits, hybrid
research: LLM prompt strategies for tip generation quality
feat: signal source abstraction — generalize beyond Todoist
refactor: generalize recommendation pipeline — candidate → rank → render stages
feat: AI tip generation via Ollama — contextual advice from user signals
bug: no data retention purge for tip_scores and tip_feedback (GDPR 30-day)
bug: reward updates to ml/serving silently swallowed on failure
bug: Todoist access tokens never refreshed — silent failure after expiration
bug: TipFeedback type includes helpful/not_helpful but backend rejects them
bug: port mismatch — config.ts defaults to 3078, docker-compose uses 3001
Modular-monolith packaging + import-boundary lint
Moving to M4: import-boundary lint (eslint-plugin-boundaries) becomes important at scale. Low risk for now with single developer.