feat: feedback-driven recipe discovery (auto-ingest via Spoonacular)
CI / backend (pytest + alembic) (push) Has been cancelled
CI / frontend (build) (push) Has been cancelled

This commit is contained in:
2026-05-24 13:17:39 -07:00
parent 35f736a052
commit 3885d7d0dc
20 changed files with 1962 additions and 9 deletions
+56
View File
@@ -0,0 +1,56 @@
# 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)