Repository navigation
feat(release): the release-candidate build with every late fix, the goal path and the safety sweep green - #188
Merged
Merged
Conversation
…ort from the base branch Hosted build-and-test failed at the PR head with compile errors in ReverseScanService.swift and ReverseScanMealView.swift (ScoredRecipeID ?? Int64), inherited from the base branch at the original branch point; the base branch fixed exactly this in 832c592 and 3826378. Merging the base head resolves the inherited breakage; those commits touch only apps/ios sources and tests. Co-authored-by: Sam Gu <sgu07966@gmail.com>
… on nil recipe identity Review findings 1 and 3 on PR #170 (comment 6205336377): - The trunk integration test ingested the same store-loaded array into both engines, so its parity assertion held by construction. The direct baseline is now rebuilt from the meal log's writer shapes (three 5-star cooked events, each anchoring its own cook transaction, plus one rated event linked to the last cook); only the store's identity and replay-order columns (id, at) are borrowed so the engine's lazy decay sees the same instants on both sides. The shared Linux slice gains the same parity test over fully controlled records, and a mutation check (kind misread in the store's read path) trips it: 1.771 vs 0.328 contributions. - events(recipe:) and latestCookEventId(for:in:) bound recipe.source into recipe_source = ?, so a contract ref with nil source silently matched nothing. Both query entry points now throw TasteStoreError.unresolvableRecipeIdentity; fail-first tests recorded two failures before the guard landed. Local: taste-store-check 52/52 after re-pinning (49 before). Co-authored-by: Sam Gu <sgu07966@gmail.com> Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
…its the kcal fields An exemption entry missing old_kcal or new_kcal previously passed silently: abs(entry.get(field, nan) - value) is always False for NaN, so the must-reproduce-both-values contract held only when the fields existed. Report the missing field explicitly instead. The new regression test fails before this fix (planted field-less exemption produced zero errors) and passes after; full data/recipes/tools suite is 18 passed with the one pre-existing environmental byte-identity failure unchanged. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The claims schema has no low-carb field, so no catalog recipe can prove keto compliance, while the legacy pool enforces the .lowCarb tag mask — without this arm a keto user loses every legacy result yet keeps every catalog result. Fails-first: testKetoDietExcludesCatalogPoolFailingClosed reproduces the ungated catalog entry before the gate arm lands. Co-authored-by: Sam Gu <sgu07966@gmail.com>
Catalog entries materialize as nil-id legacy stand-ins, so Start Cooking rendered an empty guide, loadIngredients returned nothing, and Le Chef received zero ingredient context. Add catalogCookPacket(for:) and cookPacketIngredients(_:) on the repository — the single structured path — and route the preview drawer, the cooking guide, and the assistant context through it. Fails-first: the packet path had no repository API before this commit and testCatalogRecommendationYieldsCookPacketAndBridgedIngredients pins non-empty steps and bridged ingredient lines for a catalog result. Co-authored-by: Sam Gu <sgu07966@gmail.com>
TasteEventStoreTests declared cookedEvent -> TasteEvent while constructing a TasteEventRecord, which Linux Swift 6.4 rejects with 16 conversion errors (reproduced in the portable harness; fails-first). Ports trunk commit 9de2985 so the Linux portable checks compile on this lineage too. macOS CI compiles both forms; semantics are unchanged. Co-authored-by: Sam Gu <sgu07966@gmail.com>
Two review findings, both in glue no test exercised: the guide resolved the cook packet only through a legacy integer id, so catalog-native recommend results (Recipe(id: nil, ...)) fell back to the legacy path with a synthetic ref, and the journal computed macros from legacy ingredient rows instead of the frozen snapshot the meal was logged against. The gate is extracted from CookingGuideView into a static helper so tests drive the exact production resolution; the journal test logs a real catalog meal through the full flow and asserts the journal reports the snapshot. Both new tests fail at this head — the helper and journal still resolve the old way; the next commit fixes them. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The iOS-only helper above the Linux-mirrored slice was declared -> TasteEvent while constructing a TasteEventRecord, so the macOS test build failed with seven type-mismatch errors the mirror cannot see (the slice region regenerates its own helper from the committed preamble). Match the preamble's return type. Co-authored-by: Sam Gu <sgu07966@gmail.com>
… staples Review round on PR #178 (five findings), each pinned by a failing-first regression test in LeChefPlanWeeklyTests: - Blocked substitutes are never offered or applied: the snapshot drops swaps whose substitute is a household allergen, and the allocator refuses any swap whose substitute an eater blocks (previously only recipe lines were screened). - Stock is claimed within a dinner: a line's swap sees the pool minus what earlier lines of the same dinner already claimed, so the substitute line reports its real remainder instead of hiding it. - Leftover surplus is tracked per cooked dinner: a leftovers night re-serves one dish and must be covered by that dish's own surplus, never by portions pooled across different dishes. - Saved catalog dinners reload their numeric identity (the negative digit tail of the rcp- id) instead of 0, keeping replacement and exclusion working after a plan reload. - Catalog assumed_staple defaults yield to an explicit household pantry tier: an ingredient marked only_if_confirmed is never re-assumed. Verified: Linux scratch harness 48/48 (the six new/updated tests fail before the fixes and pass after). Hosted macOS CI runs the app-target suite. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The fail-first run proved both review findings (38835855949 red at 5c8ac46): the catalog-native gate test got nil content, and the journal reported 0.0 kcal where the frozen snapshot says 840. The guide now resolves catalog content from the result's own catalog ref when there is no persisted integer id — the shape the recommend pool builds for every catalog-native recipe — keeping the legacy bridge and the parsed-instructions fallback for drafts and unloadable packets. The journal reports the frozen per-serving nutrition snapshot at the linked revision, scaled by servings consumed and portion multiplier, and keeps the legacy ingredient math for cooks with no catalog link. The bridge test inserts the legacy recipe before referencing it (FK order). Co-authored-by: Sam Gu <sgu07966@gmail.com>
… bundle types Review fixes (comment 6205308578): Finding 1: apply logged the exposure from the input pool before reordering, so once the learned layer is on the logged slate was not the order the user saw — a promoted recipe never accrued skip/view evidence against a slate it appears on and slatePosition indexed the wrong entries (SPEC 2.4 pins the exposure as the shown slate, ordered). Reorder first, then log; the current render's exposure also stays out of its own ranking inputs. The exposure test now asserts the displayed (learned) order and fails against the old code. Finding 2: the taste-store-check mirror failed to build — the mirrored TasteProfileRepository referenced TasteCatalogFeatureIndex, which the mirror does not carry (reproduced at c149e08 on Linux Swift 6.4.1: cannot find type 'TasteCatalogFeatureIndex' in scope). Declare a TasteCatalogFeatureIndexing seam next to its only consumer; the concrete index conforms in the app target and the mirror compiles the repository against the protocol alone. The portable suite passes 50/50 after the change. test.sh gains a Swift 6.4.1 fallback path: GRDB 7.10 needs tools >= 6.1, so the stale 6.0.3 entry can no longer resolve the graph. Co-authored-by: Sam Gu <sgu07966@gmail.com>
…alog The committed golden fixtures were regenerated over recipes-v2.json, so the README's validate/regenerate commands still passing the legacy data.json dead-ended with golden-hh23 ranking mismatches. Verified failing-first with the legacy path and replaying exactly with the v2 path. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The finding-1 assertion flip was left uncommitted by 04ffc3c, so CI ran the new reorder-then-log service against the old expectation and failed with the inversion it was written to catch: the logged slate is the learned ["3", "2", "1"], not the rule order ["3", "1", "2"]. Co-authored-by: Sam Gu <sgu07966@gmail.com>
RecipeCatalogNutrition lives in the FLFeatureLogic package module; RecipeRepositoryCatalog already imports it, UserDataRepository did not. Co-authored-by: Sam Gu <sgu07966@gmail.com>
…s and transport failures - Leave keeps the local Table until the server accepts; an owner's leave surfaces ownerCannotLeave before any request is sent (the backend refuses it with 409). - Join and createTable transport failures enqueue outbox events so intent survives; a pending join restores as asking-to-join after relaunch (community_table_link_v2). - Restore keeps tokens when the refresh leg could not run and clears them only on a server rejection; refresh persists the fresh account snapshot it carries. - The in-memory token store serializes async access with NSLock.withLock (Apple SDK forbids lock/unlock across await). - Failed no-content responses keep their bodies so typed server errors surface. Review round for PR #173 findings 1-7, each with a failing-first regression test. Co-authored-by: Sam Gu <sgu07966@gmail.com>
- CommunityStore.swift:464: Data(row["payload_json"]) has no exact initializer match on the Apple SDK (resolved only on Linux); read the column typed per the file's existing pattern and treat a NULL payload as no cache. - CommunitySessionService.swift: with try? optional flattening (SE-0230) the paired tokens != nil comparisons were always true (compiler warnings at lines 97 and 107); compare the try? result directly. macOS CI run 38838725369 failed on the initializer; this fixes it. Co-authored-by: Sam Gu <sgu07966@gmail.com>
…endencies The packet PRs shipped the community client stack (#159/#166/#173/#179), the taste-profile repository (#165/#167/#176), and the LeChef plan sheet (#152/#178) with no app-side construction site. AppDependencies now builds them at launch: CommunityStore + CommunitySessionService (keychain token store) + the three community view models, and TasteProfileRepository over the same shipped-bundle feature index the residual ranker uses. The profile and plan-sheet view models are exposed through factories backed by the production adapters. The community backend URL resolves from COMMUNITY_BACKEND_BASE_URL (env or Info.plist), defaulting to the local dev server on port 8087. Co-authored-by: Sam Gu <sgu07966@gmail.com>
catalogMatches ranked every installed catalog row regardless of rights status. Filter to rights_status = 'original' so a rewritten recipe can never surface in Home's pool, matching the gate report's requirement that only originals are recommendable. Co-authored-by: Sam Gu <sgu07966@gmail.com>
…ndencies One end-to-end walk over a fresh on-disk database, shipped resources, and the real AppDependencies: scan-review pantry intake with a household allergen, Home's exact recommendation source under the off residual gate, a catalog cook on the guide's session construction with the structured timer and thermometer steps, a recorded timer_start proposal approved on the cooking session, the celebration-path meal log with the frozen (catalog_id, revision) nutrition snapshot and pantry consumption, the taste profile's cook evidence below the render gate, a weekly plan through the production adapter with allergen screening, and a signed-out share waiting in the community outbox. Co-authored-by: Sam Gu <sgu07966@gmail.com>
PlanSheetViewModel lives in the FLFeatureLogic framework target; the new factory needs the module import to compile. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The transport stub's async send() called NSLock.lock()/unlock() directly, which the Apple SDK forbids from async contexts (macOS CI run 38839520976). Wrap the send body in NSLock.withLock; the synchronous sentCount/at accessors keep their existing locking. Co-authored-by: Sam Gu <sgu07966@gmail.com>
LiveProposalFrames.proposal takes Data, not String; MealLogService.Outcome spells historyId with a lowercase d; and GRDB's sync read overload must be chosen from a sync context, so the async test reads through a synchronous helper shell. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The previous round's mechanical edits were lost to a concurrent write; this commit re-applies them on top of the helper additions. Co-authored-by: Sam Gu <sgu07966@gmail.com>
…y entries Of 215 vocabulary keys carrying only 'unknown', 210 now carry decisive composition classes with a recorded class_source: 47 from the suite allergen table, decisive USDA FoodData Central catalog categories for a further set, and per-key curation where catalog categories were unreliable (steak listed as vegetables, cinnamon as baked products). Ambiguous cases keep the 'unknown' fail-closed marker; five keys remain fully unknown (broth, dashi, green_curry_paste, massaman_curry_paste, stock). Mustard gains its allergen class. Co-authored-by: Sam Gu <sgu07966@gmail.com> Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com> Co-authored-by: Sam Gu <sgu07966@gmail.com> Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
…ims from evidence The bundle now carries what the app's diet and safety gates need instead of coarse proxies: - ingredients ship their vocabulary composition classes; the schema requires them. - thermometer checks cite their FSIS class and the validator checks the cited row's endpoint minimum instead of a coarse class floor, which falsely rejected valid ground-meat and leftovers checks. - authored timer_min metadata wins during compilation; text parsing remains the fallback (940 authored steps ship their exact seconds). - the compiler auto-places a charted FSIS check when a recipe's required classes are not covered by any authored safety block (none needed on the committed corpus). - vegetarian, vegan, gluten_free, and dairy_free claims are derived from line classes fail-closed: an authored true claim contradicted by a known blocking class fails validation; unknowns keep the authored value and warn. Recompiled bundle: 762 recipes, 328 ingredients, 468 thermometer checks, 1170 timered steps, derived true claims vegetarian 327 / vegan 121 / gluten_free 336 / dairy_free 306. Validator and contract checker pass; portable suite 37 passed, 1 skipped. Co-authored-by: Sam Gu <sgu07966@gmail.com> Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com> Co-authored-by: Sam Gu <sgu07966@gmail.com> Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
reach_report_v2.py resolves ten written household pantries (pantries-v2.json) against the app ingredient space by exact match only (snake_case and plural-fold candidates; every resolution rule recorded, misses disclosed) and counts, per pantry, recipes cookable with 0 and at most 2 missing required lines, split by the app's fail-closed diet gate. Shipped bundle vs this branch's build, medians across pantries (near tier, at most 2 missing lines): omnivore 129.5 -> 129.5, vegetarian 3 -> 83.5, vegan 0 -> 23.5, gluten_free 5.5 -> 60, dairy_free 3 -> 59.5. Identity reach is unchanged; the diet-gated reach gain comes from the composition classes carrying the claims. Co-authored-by: Sam Gu <sgu07966@gmail.com> Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
GRDB's sync read is a plain throwing call, so a rethrows wrapper may not forward to it. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The test calls the @mainactor signInAdult helper, sending the non-Sendable test case across the actor boundary (Swift 6 sendability error at CommunityClientTests.swift:513, macOS CI run 38840329632). Every other test in the class already carries the annotation. Co-authored-by: Sam Gu <sgu07966@gmail.com>
…t9-fridgeluck-screen-path
…t9-fridgeluck-screen-path
Two goal-path assertions described behavior the stack does not implement: - Pantry deduction: applyConsumption reads legacy recipe_ingredients by the resolved recipe id; a catalog pool entry materializes an ingredient-less legacy row, so a catalog cook deducts no stock. That is the inventory-deduction gap tracked as a feature-sized follow-up — pin the empty consumption result and unchanged total instead of asserting a drop. - Learned-layer evidence: the hidden layer's numerator counts cooks rated 2 stars or below, so a 4-star cook contributes denominator only. Assert the held low-rating claim by denominator, not numerator.
The sweep test was written without a compilable host: the recommendation surfaces take Set<Int64> pantries, HealthProfile.dietaryRestrictions is a JSON array string rather than an array, and database reads/writes inside async test bodies resolve to GRDB's async overloads and need await; the unknown-class mutation check hoists its fetch out of XCTUnwrap's autoclosure, which cannot carry async calls.
This was referenced Oct 16, 2026
Merged
loadSnapshot's read closure drives substitutions(for:in: db), whose household context and offer screening still re-entered the database queue (householdScreen's profile and vocabulary reads, verdict-time bridge lookups) — a held-transaction re-entry GRDB aborts with "Database methods are not reentrant". Add handle-based householdScreen and bridged screening variants that run every read on the caller's connection, and complete the persistence fixture's catalog-ingredient schema with the classes column the snapshot read now selects.
The screenedSubstitutions path still called substituteScreenVerdict without the bridged parameter; queue-safe callers read the bridge per query, so bridge() is correct here.
obvious-autobuild Bot
added a commit
that referenced
this pull request
Oct 16, 2026
…n land green Merge ab6c9f1 brought the safety-gates feature whose sweep suite has never run green anywhere: CI run 38856495680 fails 934 sweep assertions plus one substitution-screen case, and the rejoin line's repaired head bc155f2 (run 38855840833) fails the same signature — the breakage is base-borne on obv/burst9-fridgeluck-safety-gates, not introduced by this branch's merge. PRs #187/#188 own that repair; this branch is the LeChef socket E2E work. Reverting merge ab6c9f1 restores the aea3b8f state (alpha + goal-path tip merged), where GoalPathTests.testFridgeToMealToTasteGoalPath is green — the original blocker of this PR, fixed by carrying e87ee7b's pin of actual pantry/evidence behavior. Co-authored-by: Sam Gu <sgu07966@gmail.com> Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
The sweep drove PlanDataAdapter.loadSnapshot — which reads the household from the health_profile table — without ever seeding that table, so the weekly-plan pool screened unrestricted while the test-side re-screen used the restricted profile: blocked recipes were offered and keto candidates leaked. Seed the swept profile before loadSnapshot, screen rcp-* pool rows through the composition class screen and legacy rows (numeric ids from the weekly-plan merge) through the documented required-flagged-line filter, and guard the unrestricted pool reach instead of an exact-tier count the FDC bridge coverage cannot support in a fresh-install database. Restore the base's canonical substituteIsAllergen: the merge resolution had rewritten it into a composition recheck whose empty-bridge nil broke the explicit-id/no-diet contract (an unflagged substitute must stay allowed when no diet is active). The composition screen stays on the offering surfaces; the id/diet gate keeps the base's semantics. Flip the dropped-group-mapping mutation check to its achievable contract: the gate's group-to-class fallback keeps refusing a dropped mapping, so the mutation asserts both refusals survive. Also merge base tip e87ee7b (test-expectation alignment for the shipped bundles).
…es' into obv/burst9-fridgeluck-rejoin # Conflicts: # apps/ios/Platform/Persistence/Services/SubstitutionService.swift
…to obv/burst9-fridgeluck-rejoin # Conflicts: # apps/ios/Tests/LeChefPlanWeeklyTests.swift
Three surfaces still disagreed about the one household safety screen: catalogMatches computed the household and composition data but offered recipes without applying the verdict, so restricted households received recipes the sweep's own screen refuses. Apply screenCatalogRecipe before the claim gate, exactly as the weekly-plan and substitution surfaces do. Substitute offers without a bridge mapping returned nil (treated as blocked) even for unrestricted households, which have nothing to break; return allowed for them and keep fail-closed nil for restricted ones. The sweep fixture applied only the v2 bundle, so the identity bridge resolved nothing: it matches through `ingredients`, which was empty. Hydrate the shipped USDA vocabulary first, then the v2 catalog whose apply rebuilds the bridge against it, mirroring the app's warm-up order. The transparent-refresh test signed in without building the Apple nonce first, so SessionViewModel.signIn exited before contacting the service; build it like the canonical helper does. Co-authored-by: Sam Gu <sgu07966@gmail.com>
…sign-in The merged bound-nonce sign-in flow refuses a token minted without a nonce request; the stale transparent-refresh test skipped appleRequestNonce() and its sign-in was refused, leaving the account snapshot nil. Matches the sign-inAdult helper and the passing community-check mirror.
…to obv/burst9-fridgeluck-rejoin # Conflicts: # apps/ios/Tests/Community/CommunityClientTests.swift
…itutes ee38b90 differentiated the no-bridge-mapping guard but returned false where the verdict type needs .allowed; the caller unwraps isAllowed, so unrestricted households keep the substitute either way — as Bool the file no longer compiles.
SamGu-NRX
marked this pull request as ready for review
October 16, 2026 06:51
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. |
SamGu-NRX
added a commit
that referenced
this pull request
Oct 16, 2026
Alpha (ef236fc, via #188) already carries everything this branch adds: the lechef-e2e tool, the backend e2e boot/script, the agentServer split, GoalPathTests with the pantry and evidence pins, and the AppDependencies wiring are byte-identical on both sides. The one branch-only difference, the rights_status filter in RecipeRepositoryCatalogRecommend.swift, is also on alpha alongside the household safety gate. The automatic merge was wrong: the branch's revert of the safety-gates merge (43ae74d) made git treat alpha's repaired safety-gate code as deleted, so it silently dropped HouseholdSafetyGate, the resolver, the sweep suite and the v2 bundle classes. This merge takes alpha's tree as-is. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2 of 3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The release-candidate build with every late fix, the goal path and the safety sweep green
obv/burst9-fridgeluck-rejoin— the join branch for wave 9 and every wave 5–8 branch not contained in the previous join. Base:obv/burst9-fridgeluck-safety-gates(notmain).Human author: Sam Gu (sgu07966@gmail.com). Work performed by the Obvious Autobuild agent on Sam's behalf.
What changed and why
The previous join (
obv/burst9-fridgeluck-safety-gates) contained the safety-gate wave. Three wave-9 branches and seven older branch heads were still outside it, so the release candidate could not be cut. This branch merges, in order:obv/burst9-fridgeluck-screen-pathobv/burst9-fridgeluck-lechef-socketobv/burst9-fridgeluck-taste-gateobv/burst8-fridgeluck-joinobv/burst8-fridgeluck-goal-pathobv/burst6-fridgeluck-trunkobv/burst6-fridgeluck-catalog-cook-flowobv/burst6-fridgeluck-community-client-groupsobv/burst6-fridgeluck-taste-liveobv/burst8-fridgeluck-catalog-reachPost-merge repairs, each its own commit:
chore(tools)): the trunk merge changedTasteEventStore.swift,TasteCatalogFeatureIndex.swift, and the sharedTasteEventStoreTestsslice;refresh.shrefused to overwrite stale pins, soSOURCES.txt/TESTS.txtwere re-pinned to the merged sources andTasteStoreLinuxTests.swiftregenerated (the regenerated text matched the committed mirror — no text drift, only stale pins).test(tools)):testTransparentRefreshRefreshesTheAccountSnapshotcalledSessionViewModel.signInwithout theappleRequestNonce()preamble the merged sign-in flow requires (SPEC 3.3 nonce binding); the call silently no-oped as.signedOut. One line added; the test then exercises what it intended.fix(ios)):SubstitutionService.loadBridge(db:DatabaseQueue)/loadBridge(db:Database)returned the file-privateBridgedstruct at internal visibility — rejected by Apple toolchains, tolerated by Linux. Both are nowprivate; the only caller is internal.The wave-9 PR descriptions asked for "one-line wirings in
AppDependencies.swift" only from the screen-path PR (#185); its body is CI-status-only (verified via the issues API, no edit history), and every construction seam it needs —makeTasteProfileViewModel(),makePlanSheetViewModel(),makeRecommendationEngine(), the community view models — is already inAppDependencies.swiftfrom #182 and the wave's own commits. No additional wiring was required.How this was checked
All on Linux x86-64 Swift 6.4 (swiftly) + Bun, unless marked hosted:
python3 data/recipes/tools/compile_bundle.py→ 762 recipes, 328 ingredients; output byte-identical toapps/ios/Resources/RecipeCatalog/recipes-v2.json(determinism held through the merge).validate_bundle.pyPASS (fail-closed null claims only, by design);docs/spec/recipes/contracts/check.pyPASS (50 identity entries, 6 recipes, 6 events);pytest data/recipes/tools/tests/— 38 passed, 1 skipped (pre-existing skip).test.sh— 53 tests, 0 failures.refresh.shre-pinned 33 sources;verify.shPASS;swift test— 82 tests, 0 failures after the nonce fix above.backend/communitybun test— 138 tests, 0 fail (26 skip, pre-existing);backend/gemini-agentbun test— 338 tests, 0 fail.apps/ios/Tools/lechef-e2e run.sh): 12/12 boot checks — real WebSocket, production phone-side walk; includes the substitution recheck receipt carrying the contract-shaped allergen recheck ({"verdict":"verified","eaters":["Ana"],"blockedPath":"Contains wheat via soy sauce"}), which verifies the receipt-shape divergence PR [obvious-fleet] real-WebSocket cook-session E2E for phone and gateway, goal-path green #186 documented as open.scripts/community-e2e/run.sh): WALK PASS — 13 steps — nonce-bound 18+ sign-in, publish, Explore, Tables, report→queue→decision, challenge entry, 24 h vote gate, closed tally, restore.Bridgedreturn), 38848749128 at 46609b4 (stale snapshot identifier), 38849749630 and 38850780087 (adapter merge artifacts), 38852735186 (stale merge base — resolved by merging the advancing safety-gates tip), 38854677426 at 58eba2d (missingbridgedargument), 38855840833 at bc155f2 (runtime; the base's sweep fixes and goal-path green lineage landed in bd8af1b and were merged), 38857675958 at 917a550 (one stale transparent-refresh test missing the nonce-bound sign-in setup), 38859000781 at 78380ee (compile: an unbridged-substitute guard returnedfalsewhere the verdict type requires.allowed, fixed in 9ca20cd). Run 38860269509 at 9ca20cd: SUCCESS — build-and-test and dead-code-advisory pass; the goal path and the safety sweep run green on the merged tree. Those workflows belong to the default branch's.github; this staging lineage carries onlyios-ci.yml, matching the coverage every prior wave PR received.Unresolved review findings, PRs #166–#180
015fc30, each with a regression test (per the PR's own comment thread).5a33152(documented in the PR body dispositions; CI-verified there).canVoteAtafter refreshrefreshAccessTokennow returns the fresh account and updates the snapshot (unit-tested; community-check 82/82; community E2E step 10–11 exercises the gate live).parsedAllergenIds∪dietaryExcludedIngredientIds) and the shared safety gate; cook-time recheck blocks fail-closed incl. unknown composition (CookSubstitutionRecheck, e2e S4).1cf8a83a(per-query read; regression shipped).1317e365(read failure → blocked verdict; regression shipped).1317e365(union screening; regression shipped).appmode (P1)results/+ gate note). Revisit if an arm passes a future gate._churn_bounded_reordersplits into maximal runs and never swaps across runs, so wide gaps survive regardless of chaining (evaluation/taste-lab/taste_lab/engine.py:437).PRs #169, #170, #176, #177, #181–#187 had no unresolved bot findings on their threads; #181's and #186's bodies document their own final verification.
What was not checked
dead-code-advisoryruns on CI only.run.shis referenced by the package header but lives outsideapps/ios/Tools/community-e2e/; it is present atscripts/community-e2e/run.shand was used as committed.Assumptions
backend/communityand 1 skip in the data pytest are the same pre-existing skips documented on the wave PRs.Merge
Base is
alpha— the integration branch the late wave PRs target (retargeted during the round-nine union) — and not the repository default; per the repo's merge policy this PR is left as a draft for human review and human merge.🔗 Obvious Project · 🧵 Obvious Thread · 🔀 Obvious PR Artifact