# Sprint 7 — Verification

**Sprint:** Fix webui "empty meal plan" (date-semantics mismatch)
**Status:** code complete, awaiting deploy.
**Approach:** Option C — align orchestrator + frontend on "this week" = upcoming Monday; migrate the existing Friday-keyed plan to its equivalent Monday.

**Date of handoff:** 2026-06-05.

---

## What changed (recap)

| Layer | File | Change |
|---|---|---|
| Backend | `backend/app/services/orchestrator/runner.py:20-35` | `_current_week_start()` returns the **upcoming Monday** (today if Mon). |
| Frontend | `frontend/src/lib/utils.ts:43-83` | `isoMonday` → `upcomingMonday` (new logic). `isoMonday` kept as a deprecated alias. New `formatWeekRange(mondayIso)` helper. |
| Frontend | `frontend/src/components/WeekRangeNav.tsx` (NEW) | Shared component. Renders `[<]  Jun 8 — Jun 14  [>]` with clickable chevrons + a clickable range label (jump home) + an optional `This week` chip. |
| Frontend | `frontend/src/pages/Dashboard.tsx` | Import + 3 call-site updates. Replaces inline segmented control with `<WeekRangeNav>`. |
| Frontend | `frontend/src/pages/ShoppingList.tsx` | Same: import + 5 call-site updates, replaces both inline segmented controls (header + empty-state) with `<WeekRangeNav>`. |
| Data | `backend/scripts/fix_2026_06_05_to_2026_06_08.sql` (NEW) | Guarded `UPDATE meal_plan SET week_start_date='2026-06-08' WHERE week_start_date='2026-06-05';` with a `SELECT COUNT(*)` and a final verification `SELECT`. Optional commented-out block for 2026-05-29. |
| Docs | `Review/ui-nielsen-audit.md` + `fix-ui-audit.md` + `Review/handoff-ui-audit.md` + `docs/HANDOFF.md` + `.agent/plan.md` + `.agent/context.md` | All updated with Sprint 7 status blocks. |

**No new dependencies. No backend migration. Frontend + backend rebuild only, plus the one-time SQL data fix.**

---

## Deploy commands

Run on the deployment host (`100.108.224.12`):

```bash
# 1. Pull
cd ~/MealPlanner
git pull

# 2. SQL data fix (the user's 3-pending-items plan moves to 2026-06-08)
docker compose exec -T db psql -U mealplanner -d mealplanner \
  -f /dev/stdin < backend/scripts/fix_2026_06_05_to_2026_06_08.sql

# Expected output:
#   rows_to_migrate
#   ----------------
#                 1
#   UPDATE 1
#   COMMIT
# If you also uncomment the 2026-05-29 block, you'll see another UPDATE 1.

# 3. Rebuild backend + frontend
docker compose -f docker-compose.yml up -d --build backend frontend

# 4. (Optional) Verify the new function on the running backend
docker compose exec backend python -c "
from datetime import date
from app.services.orchestrator.runner import _current_week_start
print('_current_week_start() →', _current_week_start())
"
# Should print the upcoming Monday's date (e.g. 2026-06-08 if today is Fri 2026-06-05).
```

**Order matters.** Pull → SQL fix → rebuild. The SQL fix is idempotent (re-running is a no-op once 2026-06-05 has no rows), so it's safe to retry.

---

## Smoke checklist (browser, on `http://100.108.208.56:8082/`)

| # | Action | Expected |
|---|---|---|
| 1 | Open `/` (Dashboard) with no `?week=` query param. | URL is just `/`. Header shows the new week-range nav: `[<]  Jun 8 — Jun 14  [>]` for week 2026-06-08. Three meal cards visible (Chicken Fajitas Mon, Garlic Shrimp Scampi Wed, Breakfast-for-Dinner Veggie Scramble Fri). Plan status badge: `draft`. Total cost ~$188.98. |
| 2 | Click the range label (`Jun 8 — Jun 14`). | URL is still `/` (jump home goes to the default week). The `This week` chip is **not** visible (we're already on the upcoming week). |
| 3 | Click the right chevron (`[>`). | URL becomes `/?week=2026-06-15`. Header shows `Jun 15 — Jun 21`. Empty state appears (no plan for next-next week). |
| 4 | Click the left chevron (`[<`). | URL becomes `/?week=2026-06-08`. Header shows `Jun 8 — Jun 14`. Three meal cards reappear. |
| 5 | Click the `This week` chip (visible only when off the upcoming week). | URL clears the `?week=` param. Header shows the upcoming week again. |
| 6 | Open `/shopping-list` (no `?week=`). | Header shows the same `[<]  Jun 8 — Jun 14  [>]` nav. The "Add N to pantry" + "Reset" + "Print List" buttons are still in their normal positions. |
| 7 | Click a checkbox in the shopping list. The "Add N to pantry" button shows. | Button works as in Sprint 6 (no regression). |
| 8 | Open `/shopping-list?week=2026-06-15`. | Empty state: "No plan for that week. Go to the Dashboard and generate one, or pick a different week." The week-nav is still clickable. |
| 9 | Open `/` with `?week=2026-06-01` (a Mon that has no plan). | Empty state with "Plan the week" dropdown (F4). The week-nav shows `Jun 1 — Jun 7` with the `This week` chip visible (because we're not on the upcoming week). |
| 10 | Reload the page after each navigation. | URL is preserved; the same week is shown. (F5 URL persistence still works.) |
| 11 | Press `g d` (Sprint 5 keyboard shortcut). | Navigates to `/` with the default (upcoming) week. |
| 12 | Press `?` (Sprint 5 help shortcut). | ShortcutHelpBanner slides down with the keyboard help text. (No regression.) |

If any item fails, **stop and report** with the URL you were on, the action you took, and the observed vs expected behavior.

---

## API smoke (curl, on the deployment host)

```bash
# (a) The user's just-migrated plan lives at the upcoming Monday's key
curl -s "http://100.108.208.56:8082/api/meals?week_start=2026-06-08" | python3 -m json.tool | head -30
# Expect: 3 items, all status=pending, total ~$188.98

# (b) The old Friday-keyed date now returns null (post-migration)
curl -s "http://100.108.208.56:8082/api/meals?week_start=2026-06-05"
# Expect: null

# (c) The current calendar week has no plan (was always the case)
curl -s "http://100.108.208.56:8082/api/meals?week_start=2026-06-01"
# Expect: null

# (d) The shopping list is also keyed by the upcoming Monday now
curl -s "http://100.108.208.56:8082/api/shopping-list?week_start=2026-06-08" | python3 -c "
import sys, json
d = json.load(sys.stdin)
print('items:', len(d.get('items', [])))
print('week:', d.get('week_start_date'))
print('total:', d.get('total_estimated_cost'))
"
# Expect: items around 20, week=2026-06-08, total ~$27.35
```

---

## Things to look for

- **The webui is no longer empty.** This is the user's original complaint.
- **The week-range label is scannable.** The header shows `Jun 8 — Jun 14` (or whatever the upcoming week is) — the user requested this format.
- **The chevron brackets are clickable.** Mouse or keyboard, they step the week by 7 days.
- **The `This week` chip appears only when off the upcoming week.** Clean visual signal.
- **URL persistence still works.** `?week=YYYY-MM-DD` in the URL is respected.
- **Keyboard shortcuts (Sprint 5) still work.** `g d`, `g r`, `g p`, `g s` navigate; `/` focuses search; `?` shows help.
- **Plan-the-week (Sprint 6) still works.** The "Plan the week" button is at the same position with the same dropdown.
- **Bulk pantry add (Sprint 6) still works.** The "Add N to pantry" button on the shopping list is unchanged.

---

## Rollback (if needed)

The Sprint 7 change is small and easy to revert:

1. Revert `runner._current_week_start()` to return the most recent Friday (the original 5-line body).
2. Revert `upcomingMonday()` to return the current calendar week's Monday.
3. Revert the frontend `WeekRangeNav` swap (put the inline segmented control back in Dashboard and ShoppingList).
4. Re-run the SQL in reverse: `UPDATE meal_plan SET week_start_date='2026-06-05' WHERE week_start_date='2026-06-08';` (and similarly for 2026-05-29 if you migrated it).
5. `git revert` is also clean — all Sprint 7 work is in one or two commits if squashed.

The pre-Sprint 7 behavior is what the user reported as broken. Only revert if a regression appears that wasn't there before Sprint 7.

---

## Verification log

(Filled in by the operator after deploy + smoke.)

- [ ] `git pull` on deployment host → success
- [ ] SQL fix script ran → expected row count
- [ ] Backend rebuild → success
- [ ] Frontend rebuild → success
- [ ] Browser: `/` shows 3 meals on the upcoming week
- [ ] Browser: `[<]` and `[>]` chevrons step the week
- [ ] Browser: `This week` chip is visible only when off the upcoming week
- [ ] API: `/api/meals?week_start=2026-06-08` returns 3 items
- [ ] API: `/api/meals?week_start=2026-06-05` returns null
- [ ] No regression in Sprints 1-6

---

**Last updated: 2026-06-05** — code complete, awaiting deploy.
