The Draft board's swap guard was its mounted useMutation observer, so
leaving the week and coming back let a second swap start while the first
PUT was still pending, and Rebuild week's reset() detached a pending swap,
hiding its failure.
The week's swaps now live in the mutation cache, keyed by week: the guard,
the failure shown and the success handler all read them from there. Only
the latest swap of the week writes the plan it is answered with, and only
its failure is the week's. Rebuild week waits for a pending swap (its tile
is disabled meanwhile), and dismissing settled swaps is refused while one
is pending. A failed swap puts its day back only while the day is still,
field for field, the day it wrote, so a newer plan read survives.
Maestro task f231813c-992e-4a3b-a1a4-868cbad47415.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tapping a day tile puts it in the swapping state and opens a bottom sheet
segmented "Quest log · N | Regulars · N". Choosing a dinner swaps the day
optimistically with PUT /api/v1/plans/{weekStart}/days/{date}, landing the
server's plan on success and rolling the day back with an ErrorBanner and
Retry on failure. Dinners already this week are marked and not selectable.
Maestro task f231813c-992e-4a3b-a1a4-868cbad47415.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>