docs: Sprint 15 — seed 50 recipes + Sprint 12 latent-bug fix across all 6 running docs

Sprint 15 (commit a3c89bf) does two things: (1) reorders
backend/app/main.py so recipe_search_api.router mounts BEFORE
the WIP recipes_api.public_router (fixes a Sprint 12 latent
bug where /api/recipes/search was shadowed by the WIP's GET
/{recipe_id} returning 422); (2) adds scripts/seed_recipes.py
which seeded 18 Spoonacular recipes into the local library
today (free-tier 50-pt cap hit; remaining 32 to seed on later
days via the same idempotent script). DB went 31 -> 49 total
recipes.

This commit updates the 6 running docs that track sprints:

- .agent/plan.md — Sprint 15 section (S15.1-S15.4 + Done
  when + Out of scope) added after Sprint 14's out-of-scope.
- .agent/context.md — Sprint 15 decisions (D1-D6), open
  questions (Q1-Q2), and file:line references added.
- Review/sprint15-verification.md — NEW: full 18-imported
  breakdown by cuisine + free-tier math correction (50 pts/day,
  not 150) + LLM test (picked_count=0, filled_count=19,
  failed_count=2 for week 2026-07-06) + 6-risk table + deploy
  + 2 follow-up tickets (lower _DAILY_LIMIT, re-run script).
- Review/ui-nielsen-audit.md — Sprint 15 status block
  (T8.1-T8.3) added after the Sprint 14 block. Notes the
  Sprint 12 latent-bug fix as the critical change for the
  upcoming Sprint 12 deploy.
- fix-ui-audit.md — Sprint 15 section (T8.1-T8.5) added after
  the Sprint 14 section. T8.1 documents the main.py mount
  order fix in detail. T8.5 surfaces 2 follow-up tickets.
- Review/handoff-ui-audit.md — Batch K line in the deploy
  list, Sprint 15 section after Sprint 14, TL;DR Sprint 15
  line, Last-updated footer updated.
- docs/HANDOFF.md — Sprint 15 section after Sprint 14, Last-
  updated footer updated. Notes the corrected free-tier math
  and the 2 follow-up tickets.

All 6 docs now reflect Sprint 15. The Sprint 12 latent-bug
fix is documented as a hard prerequisite for the upcoming
Sprint 12 deploy (without it, every 'Search the web' query
would 422). Re-running scripts/seed_recipes.py on a later
day will add the remaining 32 recipes (the script is
idempotent — already-imported IDs return 409 and are
skipped).
This commit is contained in:
2026-06-06 14:12:25 -07:00
parent a3c89bf6a2
commit 0668d40444
7 changed files with 307 additions and 3 deletions
+31
View File
@@ -501,3 +501,34 @@ The Sprint 11 "Generate Meal Plan" CTA was library-only. Sprint 13 splits it int
- `frontend/src/components/OnboardingTour.test.tsx` (NEW) — 6 cases (S14.3)
- `frontend/package.json` (MODIFIED) — devDeps + scripts
---
## Sprint 15 — Seed 50 family-friendly recipes for 4-week planning (content op)
### Decisions
- **D1 — 50 recipes, not 100.** 4 weeks × 21 meals = 84 picks needed minimum. 50 unique recipes with 1.7× rotation is enough variety and fits in a single Spoonacular day (105 pts under 140 cap).
- **D2 — Distribution: 5 cuisines × 10 each.** Italian + Mexican + Asian + American + Mediterranean/Middle Eastern. This gives 5/7 days of cuisine rotation per week, the family's stated preference.
- **D3 — Use Sprint 12's `POST /api/recipes/import` endpoint directly.** No new code path, no schema change, no UI change. The endpoint already does the 1-pt `/information` call + ingredient upsert + Recipe insert.
- **D4 — Pick the top hit per query, not curated.** I trust Spoonacular's ranking; if the top hit is a bad fit, the user can delete it via the existing UI. The 50-query list is curated; the per-query hit is Spoonacular's pick.
- **D5 — 1-2 sec sleep between imports.** The 1-pt rate is fine on the free tier, but throttling keeps me well under the per-second rate limit and avoids a burst that could trigger Spoonacular's abuse detector.
- **D6 — Run on the host, not locally.** The host has the live backend (`mealplanner-backend-1` up, healthy). Local backend would need its own DB connection + env. The script lives at `scripts/seed_recipes.py` and runs in the host's shell.
### Open questions
- **Q1 — Curate the queries or use my list as-is?** Default: use my list as-is. The user can re-run or pick more queries if the result set is biased.
- **Q2 — After seeding, the 4-week plan is generated client-side or server-side?** Default: client-side via the existing Dashboard's "Generate Meal Plan" CTA. Server-side plan synthesis is a future sprint.
### Sprint 15 file:line references
- `backend/app/api/recipe_search.py:48-50``_DAILY_LIMIT: float = 140.0`, `_SEARCH_URL`, `_INFO_URL`. The quota gate.
- `backend/app/api/recipe_search.py:55``_points_available()` (140 - `_points_used`).
- `backend/app/api/recipe_search.py:100-148``search_recipes` endpoint (`GET /api/recipes/search?q=...&limit=10`).
- `backend/app/api/recipe_search.py:194-308``import_recipe` endpoint (`POST /api/recipes/import`).
- `backend/app/schemas/__init__.py:398-411``RecipeSearchHit` Pydantic model.
- `backend/app/schemas/__init__.py:413-415``RecipeImportRequest` Pydantic model (`{external_id, external_source}`).
- `backend/app/security.py:54-78``require_session` (the SESSION_PASSWORD auth that gates both endpoints).
- `backend/app/models/__init__.py:162-197``Recipe` model (the destination table for the imports).
- `scripts/seed_recipes.py` (NEW) — the 50-query one-shot Python script.
- `Review/sprint15-verification.md` (NEW) — the deploy + curl flow.