Integrates cf-core reranker into the L1/L2 recipe engine. Paid+ tier
gets a BGE cross-encoder pass over the top-20 FTS candidates, scoring
each recipe against the user's full context: pantry state, dietary
constraints, allergies, expiry urgency, style preference, and effort
preference. Free tier keeps the existing overlap sort unchanged.
- New app/services/recipe/reranker.py: build_query, build_candidate_string,
rerank_suggestions with tier gate (_RERANKER_TIERS) and graceful fallback
- rerank_score field added to RecipeSuggestion (None on free tier, float on paid+)
- recipe_engine.py: single call after candidate assembly, before final sort;
hard_day_mode tier grouping preserved as primary sort when reranker active
- Fix pre-existing circular import in app/services/__init__.py (eager import
of ReceiptService triggered store.py → services → receipt_service → store)
- 27 unit tests (mock backend, no model weights) + 2 engine-level tier tests;
325 tests passing, no regressions