Repository navigation
feat(data): repair catalog identity pins and aliases for pantry reach - #192
Conversation
The v3 reach replay (evaluation/catalog-reach/reach_report_v3.py) replays the app's own IngredientRepository.search over the ten written pantries and classifies every lost recipe line. Baseline on the shipped catalog: exact medians 0.5/0.5/0.0/0.0/0.0 (omnivore/vegetarian/vegan/GF/DF), near-miss medians 101/54/22.5/42.5/44.5, with 535 lines lost to search misses, 2037 to wrong-ID landings, and 1220 to unbridged keys. Repairs, all cited from the FDC bulk CSVs (/tmp/fdc scratch): - repin 12 vocabulary keys to the right FDC rows (banana, sugar, cinnamon, lentils 172420, bacon, almonds, heavy cream, white rice, canned tomatoes, pork chop, chicken thigh, chicken_thighs 2706027 which pointed at the chicken-breast row) - import 9 missing FDC rows (canonical 950 -> 959) and extend the import tool's energy ids with 2047 (Atwater General kcal) so Foundation rows without 1008 keep their energy - curate canonical displays so typed pantry terms rank the intended food (Ground Beef, Brown Sugar, Tomatoes, Potatoes, ...), add 15 alias sets, and remove the chives description's misleading 'eggs' - rename FNDDS 2705413 to Coconut Milk Beverage: its 31 kcal/100g macros are the beverage, and its old display exact-matched and hijacked the 'coconut milk' query away from the cooking row - all edits recorded in scripts/data/catalog/reach-v3-identity-edits.json Bridge: RecipeCatalogIngredientBridge now unions independently resolved legacy-ID and FDC-ID evidence instead of strict legacy-first precedence (+ resolvedByLegacyAndFDC coverage count), with a Swift test for a key whose legacy and FDC evidence resolve to different app rows. After: exact medians 4.5/1.5/0.0/2.5/2.0, near medians 162.5/93.5/29.0/76.0/78.0; classes a and b eliminated (0 lost lines each); the 46 unbridged keys remain disclosed, unresolved on purpose. Co-authored-by: Sam Gu <sgu07966@gmail.com>
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
CI run 38853183616 failed: the Coverage memberwise init received resolvedByLegacyAndFDC but the struct never declared it. Add the field. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The branch was cut from the rejoin tip before the safety-gates merge landed; the stale merge base reproduced the base's already-fixed GoalPath/CommunityClient runtime failures and GRDB reentrant fatals on hosted CI. Merging the rejoin tip brings the fixed base forward. Co-authored-by: Sam Gu <sgu07966@gmail.com>
Rejoin tip 58eba2d merged its safety-gates refactor but left the household-screened compactMap calling substituteScreenVerdict without the bridged argument its signature now requires; the same compile error fails both the base branch's run 38854677426 and this branch's 38854866877. Read the bridge per query, matching the surrounding calls. Co-authored-by: Sam Gu <sgu07966@gmail.com>
A key bridged by both evidence paths decremented resolvedByFDCID without ever incrementing it, dragging resolvedKeys below the true count (CI 38856690375: resolvedKeys 0, resolvedByFDCID -1). The union class already owns the key; only the provisional legacy count needs unwinding. Co-authored-by: Sam Gu <sgu07966@gmail.com>
…to obv/burst10-fridgeluck-pantry-reach
The corrected per-100g macros flow through per-serving nutrition, which flips the nutrient feature flags the learned arm reads; rule scores recompute for the touched recipes. Events are unchanged (same cooking history), ranking reorders only where rule scores moved. Regenerated with the documented command at the fixtures' committed seeds (hh00/7, hh01/11, hh23/13); validate-fixtures replays exactly. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The catalog loader resolved each line key to one canonical bridge id (LIMIT 1), so a union-bridged key hid its other identities from the plan's allergen screen, and both plan-path screens ignored blocked ingredients on optional lines — unlike the recommend path's whole-recipe exclusion. Allergens are hard filters: the pool screen now checks every id each line key bridges to, and the legacy-candidate and allocator screens block on any line, required or not (GoalPathTests catches the assigned allergen recipe under truthful identities). Co-authored-by: Sam Gu <sgu07966@gmail.com>
…to obv/burst10-fridgeluck-pantry-reach
…llocation The loader-level allergen screen rejected a blocked legacy recipe's catalog successor before the successor policy could stand it in, and blocked the legacy recipe itself, breaking the raw-inventory contract the weekly tests pin (candidates stay unfiltered; allergens ride the eaters list). The hard filter lives in the allocator: restrictionClean blocks any line, required or not, so rice-anchored recipes are never chosen while both the legacy recipe and its successor stay in the pool. Co-authored-by: Sam Gu <sgu07966@gmail.com>
A plan line carries one bridged ingredient id (the LIMIT-1 resolution), but a key can bridge to several app-ingredient ids and the blocked allergen can be a different id of the same food — the allocator's restrictionClean missed it and the plan assigned an allergen recipe. PlanCandidateLine now carries every id its canonical key bridges to (defaulted, so legacy and sentinel lines and existing call sites are unchanged), the adapter fills it from the bridge table, and restrictionClean screens the union. Screening input only: the candidate pool stays raw per the weekly tests' contract. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The defensive duplicate-line merge rebuilt the line without the bridged-id set; merged lines would have lost the union and the hard filter missed them. The merge unions the sets like it unions required. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The adapter edit that passes bridgeIDsByKey into each bridged PlanCandidateLine was lost to a concurrent same-file write, so every catalog line shipped an empty union and the allocator's bridge screening was vacuous — the GoalPath allergen recipe stayed assignable. Re-applied: the line now carries every id its key bridges to, matching the raw-pool contract (screening input only, no pool filtering). Co-authored-by: Sam Gu <sgu07966@gmail.com>
…ry id The weekly-plan hard filter read only each line's primary ingredient id (the bridge's LIMIT-1 resolution) while the household's blocked set held the id the profile stored. The onion key bridges to both the legacy id (5) and the USDA id (566); a household blocking 566 left every onion recipe eligible because the line's primary id was 5 — the failing GoalPath assert (the plan never assigns an allergen recipe). The shipped bridge unions already sit on PlanCandidateLine.bridgedIngredientIDs and the type's contract says the allocator screens the whole set; the filter now does. An earlier commit under this intent lost its edit to a concurrent same-file write (the same loss 70663dd documents for the adapter). Verified on Linux against the production allocator (plan-repro harness, shipped recipes-v2 bundle + USDA catalog, 762 catalog recipes): - old filter, blocked {566}, candidate line id 5 with union {5, 566}: allocated (picked=1) — the GoalPath failure shape - fixed filter, same fixture: refused (picked=2) - full weekly horizon: the union screen rejects all 195 allergen-bearing candidates; every dinner clean Co-authored-by: Sam Gu <sgu07966@gmail.com>
PlanDataAdapter conflict: both sides read the full catalog bridge per key. Kept alpha's map (admission screens every bridged id against the excluded ids) and passed the same map to each line's bridgedIngredientIDs so the allocator's hard filter also sees the whole union. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Note Review skipped Codemetrics is installed on this repository, but it hasn't been added to your team yet. To enable AI code reviews for this repo, go to your dashboard and add FridgeLuck to your team's repositories. |
…pin-audit fix(data): correct calorie rows behind #192's ingredient re-pins (kcal audit)
What changed and why
Goal: real pantries reach exact catalog matches through the app's own lookup. The v2 reach report showed exact-match medians at or near zero for every household policy, with lost lines caused by search misses, wrong-ID matches, and unbridged recipe keys.
Catalog identity repairs (13 files): repinned 14 vocabulary FDC citations (banana, sugar, cinnamon, lentils → 172420, bacon, almonds, heavy cream → Atwater 2047 energy, white rice, canned tomatoes, pork chop, chicken thigh, coconut milk → 170172, chicken_thighs → 2706027), imported 9 missing FDC rows, and applied 36 curated catalog edits (display names, aliases, the chives description). The canonical SQLite grew 950 → 959 records (3,942 unique aliases); the shipped SQLite, static nutrition dataset, recipe bundle, and manifest SHA-256 are rebuilt and refreshed.
Search-first identity: typed queries now resolve to intended identities —
eggs→ Egg,chicken breasts→ Chicken Breast,basmati rice→ Basmati Rice,canned tomatoes→ Canned Tomatoes,brown sugar→ Brown Sugar,coconut milk→ the cooking row,ground beef→ Ground Beef,chicken thighs→ Chicken Thigh.Bridge union semantics:
RecipeCatalogIngredientBridge.rebuildnow unions independently resolved legacy-ID and FDC-ID evidence (a key carrying both bridges both id sets, provenancelegacy_id+fdc_id, newresolvedByLegacyAndFDCcoverage count) instead of strict legacy-first precedence, with a new test for the both-evidence case.Measured result (
evaluation/catalog-reach/reach_report_v3.py, before → after over the ten pantries): exact medians 0.5/0.5/0/0/0 → 4.5/1.5/0/2.5/2.0 (omnivore/vegetarian/vegan/gluten-free/dairy-free); near medians 101/54/22.5/42.5/44.5 → 162.5/93.5/29/76/78. Lost required lines: 535 search misses → 0; 2,037 wrong-ID matches → 0; 1,220 lines unbridged (unchanged, disclosed); 28,123 → 28,131 genuinely-not-in-pantry.How I checked it (commands and results)
uv run usda validate— 959 records, 3,942 unique aliases, 14 required terms, all pass.python3 scripts/data/catalog/validate_bundle.py— pass. Recipe gate suite — pass.validate_corpus.py— 94.48% of 762 recipes resolved across all 14 bands. Taste-lab fixtures replayed exactly; taste-lab Python suite 17/17.reach_report_v3.pybefore/after replay — numbers above; alias and search resolutions verified directly against the rebuilt SQLite.swiftc -parseonRecipeCatalogIngredientBridge.swiftandSubstitutionService.swift— clean (syntax only).PlanAllocating.allocateover the shippedrecipes-v2bundle + USDA catalog, 762 recipes / 345 bridge rows): with the pre-fix filter and onions blocked via 566, the onion recipe (primary id 5) was allocated (picked=1 — the GoalPath failure shape); with the fix it is refused (picked=2). Full weekly horizon: the union screen rejects all 195 allergen-bearing candidates; every dinner clean.resolvedByFDCIDwithout incrementing it,resolvedKeyssummed to 0) — fixed on a24357d; run 38858662575 (head d15ccea) isolated the plan-path allergen-screen gap and the stale taste goldens — fixed on 9f20529/a04c6351.git show HEAD:<path>after every push.Safety screen correction this PR carries
Truthful bridging exposed a plan-path gap the pre-existing GoalPath assertion pins: the catalog loader resolved each line key to ONE canonical bridge id (
LIMIT 1), hiding a union-bridged key's other identities, and both plan-path allergen screens ignored blocked ingredients on optional lines — unlike the recommend path's documented whole-recipe exclusion.PlanDataAdapternow screens every id each line key bridges to against the raw allergen ids, and both the legacy-candidate screen and the allocator'srestrictionCleanblock on any line, required or not. Allergens are hard filters; the planner never waives an exclusion to widen the pool. A final CI round (432f4b6c) tightened the allocator'srestrictionCleanfurther: screening the line's primary id alone still missed a blocked id that rides only in the key's bridge union (the onion key bridges legacy 5 and USDA 566; the LIMIT-1 primary is 5), so the filter now also refuses any line whosebridgedIngredientIDsintersects the blocked set — with regression testtestHardFilterScreensTheWholeBridgeUnion.The taste golden fixtures were regenerated with the documented
regenerate-fixturescommand at their committed seeds: the corrected per-100g macros flow through per-serving nutrition, flipping nutrient feature flags and recomputing rule scores for touched recipes. Cooking events are byte-identical (same scenario); ranking reorders only where rule scores moved.validate-fixturesreplays exactly and the lab suite passes 17/17.Known failures not caused by this PR
Earlier runs inherited
CommunityClientTests.testTransparentRefreshRefreshesTheAccountSnapshotfrom the base branch itself (rejoin tip 917a550, run 38857675958); the base's own fix (9ca20cd4) arrived with the third merge and is included in head ce2867f. LeChef weekly-allocation failures were fixed on the rejoin tip and arrived with the merged base; the GoalPath allergen-assignment failure was fixed directly on this branch (432f4b6c) after a Linux repro showed the rejoin tip's screens still admitted union-bridged ids on the plan path.What I couldn't check
swift testfails pre-existing (no such module CoreGraphicsin FLFeatureLogic) — not introduced here, not a runnable gate.Assumptions
reach_report_v3.pyreplay mode.Human author: Sam Gu (sgu07966@gmail.com)
🔗 Obvious Project · 🧵 Obvious Thread · 🔀 Obvious PR Artifact