Adds 10 new secondary use entries and corrects all 8 existing ones.
New: apples/soft, leafy_greens/wilting, tomatoes/soft, cooked_pasta/day-old,
cooked_potatoes/day-old, yogurt/tangy, cream/sour, wine/open,
cooked_beans/day-old, cooked_meat/leftover.
Corrections: milk uses (specific recipes, not 'baking'/'sauces'); dairy uses
expanded; cheese label well-aged→rind-ready with named dishes (minestrone,
ribollita); rice uses (onigiri, arancini, congee); tortillas warning added;
bakery uses and synonyms expanded to named pastries; bananas synonyms
(spotty/brown/black/mushy); rice synonyms (old rice).
New fields on every SECONDARY_WINDOW entry:
- discard_signs: qualitative cues for when the item has gone past its
secondary window (shown in UI alongside uses)
- constraints_exclude: dietary labels that suppress the entry entirely
(wine suppressed for halal/alcohol-free)
ExpirationPredictor.filter_secondary_by_constraints() applies constraint
suppression; _enrich_item() now accepts user_constraints and passes
secondary_discard_signs through to the API response.
Secondary-state items (stale bread, overripe bananas, day-old rice, etc.)
are now surfaced to the recipe engine so relevant recipes get matched even
when the ingredient is phrased differently in the corpus (e.g. "day-old
rice" vs. "rice").
Backend:
- Add rice and tortillas entries to SECONDARY_WINDOW in expiration_predictor
- Add secondary_pantry_items: dict[str, str] field to RecipeRequest schema
(maps product_name → secondary_state label, e.g. {"Bread": "stale"})
- Add _SECONDARY_STATE_SYNONYMS lookup in recipe_engine — keyed by
(category, state_label), returns corpus-matching ingredient phrases
- Update _expand_pantry_set() to accept secondary_pantry_items and inject
synonym terms into the expanded pantry set used for FTS matching
Frontend:
- Add secondary_pantry_items to RecipeRequest interface in api.ts
- Add secondaryPantryItems param to _buildRequest / suggest / loadMore
in the recipes store
- Add secondaryPantryItems computed to RecipesView — reads secondary_state
from inventory items (expired but still in secondary window) and builds
the product_name → state_label map
- Pass secondaryPantryItems into handleSuggest and handleLoadMore
Closes#83