Repository navigation
fix(cook-mode): reserve swap consumption splits and re-arm timer alerts on resume or adjust - #190
Conversation
A swap-covered line consumes grams from two ingredients — the original's covered share and the substitute's shortfall cover — but save persisted only the full requirement against the original and loadReservedGrams ignored the swap entirely: the substitute's consumed grams stayed double-bookable by the next plan. PlanSwap now records the consumed split (originalGrams, substituteGrams); the allocator populates it when it applies a swap, and loadReservedGrams reserves each side against its own ingredient, falling back to the legacy full-requirement math for rows saved before the split existed. Fails-first evidence (portable Linux harness, Swift 6.4 / GRDB 7.10): - RED: testSavedSwapReservesEachIngredientItsOwnConsumedShare failed with exactly the bug — original available 200 (full 300 reserved) vs 300 expected, substitute available 400 (nothing reserved) vs 300 expected. - GREEN after the fix: LeChefPlanAllocatorTests 21/21, LeChefPlanPersistenceTests 12/12. Co-authored-by: Sam Gu <sgu07966@gmail.com>
…nd adjust Resume and adjust passed label: nil into the effect run, and the scheduling effect drops updates without a label: a paused-then-resumed timer had no alert at all and an adjusted timer kept its stale deadline. All three timer mutations now pass the timer's own stored label; cancel effects ignore it. Validation is macOS-CI-only: the view model imports UserNotifications, so the new CookModeViewModelTimerAlertTests cannot run in the portable Linux harness. 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 |
The previous commit carried the three storedTimerLabel call sites but lost the helper definition — the macOS build failed with "cannot find 'storedTimerLabel' in scope". Re-add private func storedTimerLabel(id:) after perform. Co-authored-by: Sam Gu <sgu07966@gmail.com>
The call sites invoked storedTimerLabel(id) without the argument label; the Linux parse pass cannot catch name-resolution, and macOS CI flagged the three sites. Co-authored-by: Sam Gu <sgu07966@gmail.com>
storedTimerLabel(id:) parsed as an unapplied function reference; the call needs the argument value — storedTimerLabel(id: id). Comment order around the call sites restored. Co-authored-by: Sam Gu <sgu07966@gmail.com>
|
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. |
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. |
Why
Greptile review 5542992530 on PR #181 posted six P1 findings. This PR fixes two of them — finding 3 (timer alerts stop matching after pause/resume/adjust) and finding 5 (saved swaps reserve the wrong stock) — on minimal branches so they can merge independently of PR #188.
What
Finding 5 — saved swaps reserve wrong stock (fixed, 368c0a1). A swap-covered plan line consumes grams from two ingredients: the original's covered share and the substitute's shortfall cover. Save persisted only the full requirement against the original, and
loadReservedGramsignored the stored swap entirely, so the substitute's consumed grams stayed double-bookable by the next plan (reserving the full 300 g requirement against the original that actually supplied 200 g, and reserving nothing of the substitute's 100 g).PlanSwapnow records the consumed split (originalGrams,substituteGrams, optional); the allocator populates it when it applies a swap;loadReservedGramsreserves each side against its own ingredient. Rows saved before the split decode asniland fall back to the legacy full-requirement math, so old saved plans keep loading and reserving as before.Finding 3 — timer alerts stop matching (fixed, 81ef8d6).
resumeTimerandadjustTimerpassedlabel: nilinto the effect run, and the scheduling effect drops updates without a label: a paused-then-resumed timer had no alert at all, and an adjusted timer kept its stale deadline. All three timer mutations now pass the timer's own stored label; cancel effects ignore it.Scope note: findings 1, the journal half of 2, 4, and 6 ride PR #188 (commit 770ab5e); the inventory-deduction half of finding 2 is a documented feature-sized follow-up, intentionally not attempted here.
How to Review
LeChefPlanModels.swift—PlanSwapsplit fields, legacy init delegates to the new designated init so every existing call site compiles unchanged.PlanAllocating.swift— one-line change: the swap arm passesallocated(the original's consumed grams) andsubstituteGramsinto the swap it emits.PlanDataAdapter.swift—loadReservedGramsselectsl.swap, decodes it, and adds the split per side; the fallback path preserves pre-split behavior exactly.CookModeViewModel.swift—storedTimerLabel(id:)lookup, passed intoperformfrom pause/resume/adjust;removeTimerdeliberately staysnil(its only effects are cancels).485ae82eblobs — e.g. 31 pre-existing findings inCookModeViewModel.swift); this diff introduces zero new findings, and reformatting whole files would collide with PR feat(release): the release-candidate build with every late fix, the goal path and the safety sweep green #188.Test Evidence
Portable Linux harness (Swift 6.4, GRDB 7.10.0, scratch package mirroring the plan sources and suites, outside the repo):
testSavedSwapReservesEachIngredientItsOwnConsumedSharefailed exactly as the bug predicted: original available 200.0 vs expected 300.0, substitute available 400.0 vs expected 300.0 (2 failures, 1 test executed).LeChefPlanAllocatorTests21/21 passed (including new assertions that the allocator's emitted swap records 200 g original / 100 g substitute for the 300-demand 200-stock case) andLeChefPlanPersistenceTests12/12 passed (including the new saved-swap reservation test).swiftc -parseclean on all seven touched files;swift format lint --strictintroduces zero new findings.macOS-CI-only:
CookModeViewModelTimerAlertTests(new, resumes and adjusts a timer against a recording scheduler and asserts the re-armed schedule keeps the stored label and fresh deadline) cannot run in the portable Linux harness because the view model imports UserNotifications. Its pass/fail is verified by the repository's hosted macOS CI on this branch's head, and by nothing else.Human author: Sam Gu (sgu07966@gmail.com)
🔗 Obvious Project · 🧵 Obvious Thread · 🔀 Obvious PR Artifact
CI History
storedTimerLabelcall sites but lost the helper definition (sandbox working-tree revert between edit and commit). dead-code-advisory skipped.storedTimerLabel(id:)).storedTimerLabel(id:), which Swift parses as an unapplied function reference, not a call.CookModeViewModelTimerAlertTests, covering the finding-3 validation the portable Linux harness cannot perform.Each failure was a view-model compile error on macOS only (
swiftc -parsecannot catch name resolution) — no behavior change beyond the fixes described above.