# Approved Plan — Feedback-Driven Recipe Discovery Approved: 2026-05-23 User decisions: (1) dashboard badge only for review, (2) 4-week lookback, (3) skip manual review — auto-add on discovery. ## Phase A — Feedback Analyzer - [x] Design complete (see docs/proposals/2026-05-23-feedback-driven-recipe-discovery.md) - [x] Implement `app/services/feedback_analyzer.py` - Reads feedback from past 4 weeks - Aggregates positive signals (preferred cuisines, proteins, high ratings) - Aggregates negative signals (avoided tags, ingredients, denial reasons) - Generates discovery_queries for external APIs - Outputs structured `FeedbackAnalysis` dataclass - [x] Add `feedback_analysis` JSONB column to `weekly_run` table - [x] Unit tests for analyzer logic - [x] Hook into orchestrator `step_finalize` ## Phase B — Recipe Discovery + Ingestion - [x] Implement `app/services/recipe_discovery.py` - Spoonacular client with quota tracking - TheMealDB fallback - Query builder from `FeedbackAnalysis` - [x] Implement `app/services/recipe_ingestion.py` - Normalize external recipe → our schema - Ingredient name mapping (fuzzy + canonical seed data) - Duplicate detection via external_source+external_id and fuzzy name match - Auto-add to `recipe` table (no review queue per user) - [x] Add `external_source`, `external_id`, `discovery_reason` to `recipe` table - [x] Admin endpoint: `POST /api/admin/trigger-discovery` (manual trigger) - [x] Rate-limiting and quota exhaustion handling ## Phase C — Orchestrator Integration - [x] Weekly finalize step: run analyzer → if queries found and quota available → run discovery → ingest → log - [x] Configuration env vars: - `SPOONACULAR_API_KEY` (existing) - `AUTO_DISCOVERY_ENABLED=true` - `AUTO_DISCOVERY_MAX_RECIPES_PER_RUN=5` - [x] Dashboard endpoints: `/api/meals/dashboard/discovered-count` and `/api/meals/dashboard/discovery-insights` ## Phase D — Verification - [x] End-to-end tests: analyzer, discovery, ingestion, duplicate prevention - [x] Test quota exhaustion graceful degradation - [x] Update docs and README ## Halt conditions - Spoonacular API returns unexpected schema → stop, document, fix mapper - Ingredient mapping consistently wrong → add LLM-assisted mapping or tighten threshold - Duplicate recipes slipping through → improve detection logic ## Context links - Proposal: docs/proposals/2026-05-23-feedback-driven-recipe-discovery.md - HANDOFF: docs/HANDOFF.md (updated with session notes)