Sprint 16.1 (commit 11cfd46) is a one-line fix that lowers
_DAILY_LIMIT in backend/app/api/recipe_search.py:48 from
140.0 to 45.0. The 140 value was set assuming Spoonacular's
free tier is 150 pts/day; Sprint 15 round 1 proved the real
cap is 50 pts/day. The gate now triggers at 45 (5pt safety
margin), preventing the user from making requests that
would 503 after a 402 upstream roundtrip.
This commit updates the 6 running docs that track sprints:
- .agent/plan.md — Sprint 16.1 section appended to the
Sprint 16 sections.
- .agent/context.md — Sprint 16.1 decisions + file:line
references added.
- Review/sprint16-verification.md — Sprint 16.1 section
appended (one-line change + verification).
- Review/ui-nielsen-audit.md — Sprint 16.1 paragraph added
to the Sprint 16 status block.
- fix-ui-audit.md — T9.6 added to the Sprint 16 section.
- Review/handoff-ui-audit.md — TL;DR Sprint 16.1 line
added, Last-updated footer updated.
- docs/HANDOFF.md — Tracking docs reference updated to
include Sprint 16.1, Last-updated footer updated.
All 6 docs now reflect Sprint 16.1.
Sprint 16 (commit 25e29c7) is a 2-line fix that switches
OLLAMA_MODEL from kimi-k2.6:cloud to gpt-oss:20b and bumps
max_tokens from 800 to 4000. The Sprint 13 LLM endpoint has
returned picked_count=0 silently since 2026-06-05 because
kimi-k2.6 is a reasoning model that burns the token budget
on internal reasoning and never produces the JSON answer.
The library fill (Sprint 6+) silently took over. Discovered
while answering the user's "is there anything else to refine?"
question.
Live verification: 5/5 test weeks return picked_count 15-21
(was 0/5 before). 11/11 vitest cases pass (4 new from S16 +
7 from S14). npm run build green. No new runtime deps. No
schema change. No UI change.
This commit updates the 6 running docs that track sprints:
- .agent/plan.md — Sprint 16 section (S16.1-S16.4 + Done
when + Out of scope) added after the Sprint 15 sections.
Documents the diagnosis (kimi-k2.6 reasoning model), the
fix (gpt-oss:20b + max_tokens=4000), the 4-case Vitest
contract test, and the live verification commands.
- .agent/context.md — Sprint 16 decisions (D1-D5), open Q1,
and file:line references added.
- Review/sprint16-verification.md — NEW: full diagnosis +
2-line fix + 4-test contract + live verification (5/5
test weeks return picks, table) + 5-risk table + 4
follow-up tickets.
- Review/ui-nielsen-audit.md — Sprint 16 status block added
after the Sprint 15 Round 3 block.
- fix-ui-audit.md — Sprint 16 section (T9.1-T9.5) added
after the Sprint 15 section. T9.1 documents the 2-line
fix in detail (config.py + llm_plan.py + .env). T9.5
surfaces 3 follow-up tickets.
- Review/handoff-ui-audit.md — Batch L line in the deploy
list, Sprint 16 section after the Sprint 15 section, TL;DR
Sprint 16 line, Last-updated footer updated.
- docs/HANDOFF.md — Sprint 16 section after Sprint 15, Last-
updated footer updated. Notes the corrected model choice
and the 4 follow-up tickets.
All 6 docs now reflect Sprint 16. The Sprint 13 LLM endpoint
now works as designed. Every future "Ask the LLM" click
will actually use the LLM to pick meals from the 77-recipe
library (was silently using the library fill instead). The
_ask_llm helper is still the single F9-full seam.
Sprint 15 round 2 (commit 97b84a7) added seed_recipes_round2.py
which seeded 18 more Spoonacular recipes today. Library went
49 -> 67 total. LLM test (Sprint 13 endpoint, week 2026-07-20):
{picked_count: 0, filled_count: 21, failed_count: 0}
The library now covers all 21 slots of a week (was 19/21 + 2
failed in round 1).
This commit updates the 6 running docs:
- .agent/plan.md — Sprint 15 Round 2 section (S15R2.1-S15R2.4
+ Done when + Out of scope) added after the round 1 sections.
50-query list documented by category.
- .agent/context.md — Round 2 decisions (D7-D10) added: list
focuses on cuisines round 1 didn't cover, round 2 is a
separate script, library at 67 with 21/21 LLM coverage.
- Review/sprint15-verification.md — Round 2 section appended
with: 50-query list, 18-imported result, 12 no-hits, 1 402,
updated DB state (37 Spoonacular + 30 manual = 67), LLM
test result, round 3 follow-up ticket.
- Review/ui-nielsen-audit.md — Round 2 paragraph added to the
Sprint 15 status block.
- fix-ui-audit.md — T8.6 added to the Sprint 15 section.
- Review/handoff-ui-audit.md — TL;DR and Sprint 15 section
updated with round 2.
- docs/HANDOFF.md — Round 2 paragraph added to the Sprint 15
section, Last-updated footer updated.
All 6 docs now reflect Sprint 15 round 2. Library has 67 unique
recipes — 1.25x rotation across 4 weeks of planning. Round 3
can add 30+ more by re-running scripts/seed_recipes.py on the
next day (its query list has round 1 cap-blocked American +
Mediterranean cuisines still to import).
Sprint 15 (commit a3c89bf) does two things: (1) reorders
backend/app/main.py so recipe_search_api.router mounts BEFORE
the WIP recipes_api.public_router (fixes a Sprint 12 latent
bug where /api/recipes/search was shadowed by the WIP's GET
/{recipe_id} returning 422); (2) adds scripts/seed_recipes.py
which seeded 18 Spoonacular recipes into the local library
today (free-tier 50-pt cap hit; remaining 32 to seed on later
days via the same idempotent script). DB went 31 -> 49 total
recipes.
This commit updates the 6 running docs that track sprints:
- .agent/plan.md — Sprint 15 section (S15.1-S15.4 + Done
when + Out of scope) added after Sprint 14's out-of-scope.
- .agent/context.md — Sprint 15 decisions (D1-D6), open
questions (Q1-Q2), and file:line references added.
- Review/sprint15-verification.md — NEW: full 18-imported
breakdown by cuisine + free-tier math correction (50 pts/day,
not 150) + LLM test (picked_count=0, filled_count=19,
failed_count=2 for week 2026-07-06) + 6-risk table + deploy
+ 2 follow-up tickets (lower _DAILY_LIMIT, re-run script).
- Review/ui-nielsen-audit.md — Sprint 15 status block
(T8.1-T8.3) added after the Sprint 14 block. Notes the
Sprint 12 latent-bug fix as the critical change for the
upcoming Sprint 12 deploy.
- fix-ui-audit.md — Sprint 15 section (T8.1-T8.5) added after
the Sprint 14 section. T8.1 documents the main.py mount
order fix in detail. T8.5 surfaces 2 follow-up tickets.
- Review/handoff-ui-audit.md — Batch K line in the deploy
list, Sprint 15 section after Sprint 14, TL;DR Sprint 15
line, Last-updated footer updated.
- docs/HANDOFF.md — Sprint 15 section after Sprint 14, Last-
updated footer updated. Notes the corrected free-tier math
and the 2 follow-up tickets.
All 6 docs now reflect Sprint 15. The Sprint 12 latent-bug
fix is documented as a hard prerequisite for the upcoming
Sprint 12 deploy (without it, every 'Search the web' query
would 422). Re-running scripts/seed_recipes.py on a later
day will add the remaining 32 recipes (the script is
idempotent — already-imported IDs return 409 and are
skipped).
Sprint 14 (commit 28f3212) adds Vitest + happy-dom +
@testing-library/react + @testing-library/jest-dom as
devDeps and locks the useOnboarding state-transition
contract with 7 unit tests in 25 ms. Lifts the 'no new
npm deps' rule for testing-only. Runtime bundle unchanged
(503.82 kB). No pre-existing WIP files touched.
Sprint 9's bug 1562929 (onComplete wired to .reset, the
inverse op) shipped a post-deploy fix the same day.
Sprint 14 prevents recurrence at npm test time.
This commit updates the 6 running docs that track sprints:
- .agent/plan.md — header changed to 'Active sprint: Sprint
14'; Sprint 14 section (S14.1-S14.4 + Done when + Out of
scope) added after the Sprint 13 section.
- .agent/context.md — Sprint 14 decisions (D1-D7), open Q1,
and file:line references added.
- Review/sprint14-verification.md — NEW: deploy + 7-case
test table + verification commands + Case 7 S9-bug-catch
proof + 5-risk table + open Q1 (component-level tests).
- Review/ui-nielsen-audit.md — Sprint 14 status block
(T7.1-T7.3) added after the Sprint 13 block.
- fix-ui-audit.md — Sprint 14 section (T7.1-T7.5) added
after the Sprint 13 section.
- Review/handoff-ui-audit.md — Batch J line in deploy
list, Sprint 14 section after Sprint 13, TL;DR Sprint
14 line, Last-updated footer updated. (Did NOT replace
the Sprint 7/8/TL;DR/environment-quirks/active-risks
content that was at the bottom of the file — that
material is preserved unchanged.)
- docs/HANDOFF.md — Sprint 14 section added after Sprint
13, Last-updated footer updated.
All 6 docs now reflect Sprint 14. §Future backlog
remaining: F9-full (local Ollama model pull on the host).
Q4 (Vitest) is now closed. Sprint 14 is the smallest
sprint in the cycle (devDeps + 1 test file + 2 config
files + 2 scripts) and the first that adds a test
infrastructure layer.
Sprint 13 (commit bae9403) splits the Sprint 11 "Generate Meal
Plan" CTA into a 2-step modal: "Use the recipe library" (default,
Sprint 11 unchanged) or "Ask the LLM" (new). The LLM path POSTs
to /api/llm/plan; the backend calls kimi-k2.6:cloud on ollama.com,
parses the LLM’s JSON picks, creates a fresh plan, fills the
LLM’s picks, and falls through to the Sprint 6+ fillEmptySlots
pattern for the slots the LLM didn’t cover. No pre-existing WIP
files touched.
This commit updates the 6 running docs that track the sprint:
- .agent/plan.md — Sprint 13 section (S13.1-S13.4) added.
- .agent/context.md — Sprint 13 (D1-D9, Q1-Q3) added; file:line
references; key takeaways.
- Review/sprint13-verification.md — new file: 3-step browser
smoke + 4 API curls + a11y check + 6-risk table + future
work section.
- Review/ui-nielsen-audit.md — Sprint 13 status block (T7.1-T7.3)
at the top, after the Sprint 12 block.
- fix-ui-audit.md — Sprint 13 section (T7.1-T7.5) added after
the Sprint 12 section.
- Review/handoff-ui-audit.md — Batch I added to the deploy
instructions; Sprint 13 section added after Sprint 12; TL;DR
table row 13 added; Last-updated footer updated.
- docs/HANDOFF.md — Sprint 13 section added after the Sprint 12
section, with a path-forward paragraph for F9-full.
All 6 docs now reflect Sprint 13. §Future backlog remaining:
F9-full (local Ollama model pull on the host) — opt-in based on
cloud-billing feedback. _ask_llm is the single seam: F9-full only
needs to swap the URL + model name.
Sprint 12 (commit 11b4595) wires the "Search the web" toggle on
/recipes to Spoonacular complexSearch, with a per-result Import
button that pulls the full recipe info (1 point) and writes a
local Recipe row. No pre-existing WIP files touched.
This commit updates the 6 running docs that track the sprint:
- .agent/plan.md — Sprint 12 section (S12.1-S12.5) added.
- .agent/context.md — Sprint 12 (D1-D9, Q1-Q3) added; file:line
references; key takeaways.
- Review/sprint12-verification.md — new file: 4-step browser
smoke + 2 API curls + quota test + a11y check + 5-risk table
+ future work section.
- Review/ui-nielsen-audit.md — Sprint 12 status block (T6.1-T6.5)
at the top, after the Sprint 11 block.
- fix-ui-audit.md — Sprint 12 section (T6.1-T6.6) added after
the Sprint 11 section, including the D-fix for the 5
pre-existing tsc errors.
- Review/handoff-ui-audit.md — Batch H added to the deploy
instructions; Sprint 12 section added after Sprint 11; TL;DR
table row 12 added; Last-updated footer updated.
- docs/HANDOFF.md — Sprint 12 section added after the Sprint 11
section, with a D-fix paragraph and a path-forward paragraph
for F9.
All 6 docs now reflect Sprint 12. §Future backlog remaining: F9
(Ollama local LLM) — a full backend proposal that plugs into the
same handleGenerateFirstPlan (Sprint 11) + recipe_search.import
(Sprint 12) seams.
Sprint 11 (commit 41154e9) wires the previously-dead
"Generate Meal Plan" empty-state CTA on the Dashboard to two
existing endpoints (POST /api/meals + POST /api/meals/{id}/fill-
empty-slots). No backend changes; no new dependencies. The
handler lives on the client for now; future F8 (Spoonacular) +
F9 (Ollama) will swap the fillEmptySlots call for an LLM call
without changing the DOM. F8 + F9 remain in the §Future backlog.
This commit updates the 6 running docs that track the sprint:
- .agent/plan.md — Sprint 11 section (S11.1-S11.3) added.
- .agent/context.md — Sprint 11 (D1-D6, Q1-Q3) added; file:line
references; key takeaways.
- Review/sprint11-verification.md — new file: 4-step browser
smoke + race test + 2 API curls + a11y check + risks + future
work section.
- Review/ui-nielsen-audit.md — Sprint 11 status block (T5.1-T5.3)
at the top, after the Sprint 10 block.
- fix-ui-audit.md — Sprint 11 section (T5.1-T5.5) added after the
Sprint 10 section.
- Review/handoff-ui-audit.md — Batch G added to the deploy
instructions; Sprint 11 section added after Sprint 10; TL;DR
table row 11 added; Last-updated footer updated.
- docs/HANDOFF.md — Sprint 11 section added after the Sprint 10
section, with a path-forward paragraph for F8/F9.
All 6 docs now reflect Sprint 11. §Future backlog remaining: F8
(Spoonacular) + F9 (Ollama) proposals, both full backend work.
Sprint 9 (commit 6e386ba) shipped a working OnboardingTour but a
broken dismiss path: clicking X / Skip / Esc / "Got it" did
nothing. Root cause: useOnboarding().reset() was wired to the
dismiss handler at App.tsx, but reset() does the inverse of
dismiss — it clears the localStorage key and flips isComplete to
FALSE, so the tour re-rendered, the early-return did not fire,
and the dialog stayed visible. Fix: commit 1562929 split the
dismiss and reset paths into two distinct callbacks (onComplete
and onReset). User confirmed browser smoke passes.
This commit updates the 6 running docs that track Sprint 9:
- .agent/plan.md — S9.4.1 sub-task (post-deploy fix) added.
- .agent/context.md — D9 (root cause + fix) + Q4 (Vitest?) added.
- Review/sprint9-verification.md — full post-deploy fix section
appended (root cause, fix, post-fix verification, lessons).
- Review/handoff-ui-audit.md — Sprint 9 status banner + Last
updated footer updated to reference the fix commit.
- fix-ui-audit.md — T3.4.1 sub-task added under the T3.4
verification gate.
- docs/HANDOFF.md — post-deploy fix paragraph added to the
Sprint 9 section.
All 6 docs now reflect the post-deploy reality. No code changes.
User-driven follow-up to Sprint 8: surface the Sprint 1-3 NeverSuggest
infrastructure on the Recipes surface so a family can pre-emptively
mark a recipe as never-suggest before it appears in a plan.
Backend (3 changes):
- POST /api/never-suggest (public, webui-facing). Idempotent on
(family, recipe, reason). Returns the row joined with recipe_name.
- DELETE /api/never-suggest/{ns_id} (public, webui-facing). Row-level
ownership check (403 if cross-family), 404 if absent.
- NeverSuggestRead.recipe_name + .ingredient_name server-side joins
via _attach_names() helper (one LEFT OUTER JOIN per kind).
- Admin path (POST/DELETE /api/admin/never-suggest) unchanged.
Frontend (4 changes):
- New NeverSuggestButton component (~290 lines). Two variants: card
(overlay on RecipeCard) and detail (text buttons in RecipeDetail
top bar). Popover with Allergy (red, window.confirm) + Dislike
(neutral, no confirm). Undo toast via showToast.undo() (Sprint 3
B12 pattern, 6s window). Pre-existing block detection shows a
Blocked state with an Unblock path.
- mealPlannerApi.neverSuggest.list/add/remove in api/index.ts.
- Recipes.tsx overlay: RecipeCard has position: relative; button is
opacity-0 group-hover:opacity-100 focus:opacity-100. e.preventDefault
+ e.stopPropagation prevents accidental navigation.
- RecipeDetail.tsx top bar: new Deny forever button group to the left
of Add to Plan.
Build: npm run build green (tsc 0 errors, vite 0 errors) on
docker-willester. Bundle 487 -> 495 kB. No new dependencies. No
migration (NeverSuggest table exists from prior sprints).
Tracking: Review/sprint10-verification.md (9-step browser smoke +
5 API curls + undo test + a11y check).
Hand-rolled 4-step tour (no react-joyride) anchors to existing
[data-tour="<id>"] attributes. localStorage key
mealplanner:onboarding-complete is the source of truth; ?reset-tour=1
clears the key and re-shows.
Steps: Dashboard / Pantry / Recipes / Shopping List. Keyboard: 1-4 jump,
←/→ step, Esc dismiss. Off-route fallback renders a centered card with
an 'Open <page>' CTA. A11y: role=dialog, aria-modal=true, focus captured
on open and restored on close.
5 lines of code across 4 pages; 1 new component (~420 lines). No new
dependencies. No backend changes. No migration. Frontend-only deploy.
Tracking: Review/sprint9-verification.md (8-step browser smoke + a11y
check + reset-link test).
User policy decision (2026-06-05, exact): 'Hard filter. If it is denied
this week twice, it should be considered denied for good.'
The planner had no cross-week memory of denials: a denial on
meal_plan_item.approval_status was never consulted by the planner,
and NeverSuggest (the per-family permanent blocklist) was empty for
the user. The 'Roasted Sweet Potato and Chickpea Bowl' the user
denied on 2026-05-15 was still in the planner's pool 3 weeks
later.
Implements C + Z (explicit two-button model + soft-decay +
hard-filter escalation):
- Approve: untouched.
- Deny this week (1st in 90d): denial_expires_at = now() + 90d.
- Deny this week (2nd in 90d, server-side auto-escalation):
denial_expires_at = NULL + a NeverSuggest row written.
- Never again (explicit): same as the 2nd-time auto-escalation.
Both soft and permanent denials are hard filters in the planner
(per user). A denied recipe never reappears until either the 90d
window expires or the user un-blocks via the NeverSuggest API.
Changes:
- Migration 0016: meal_plan_item.denial_expires_at (partial index)
and meal_plan_vote.denial_scope.
- 3 backend helpers (_apply_denial, _ensure_never_suggest_recipe,
_has_prior_active_soft_denial) — single source of truth for the
deny path.
- POST /api/meals/items/{id}/deny?scope=this_week|never_again
(default this_week). Returns promoted_to_permanent.
- POST /api/meals/vote/{id} extended: vote=approve|deny|never_again.
Returns denial_scope + promoted_to_permanent.
- GET /api/meals/vote/{id} HTML page renders 3 buttons; supports
one-click ?scope=... for email direct-action links.
- Email template (step_email): 3 direct-action links per recipe
plus a secondary 'open vote page' link.
- Planner: _load_blocklists returns 3 sets; soft_denied_recipes
is hard-filtered (union with blocked_recipes at the call site).
- Frontend: MealCard renders 3 buttons (Approve / Deny this week
/ Never again) for pending items. handleDeny is scope-aware;
toast reflects promoted_to_permanent. window.confirm on
'Never again' prevents accidental permanent blocks.
Verification:
- npm run build green.
- 21/21 planner tests pass (1 pre-existing test_filter_blocks_by_cost
failure is NOT introduced by Sprint 8 — verified via git stash).
- Review/sprint8-verification.md: 11-step browser smoke + 4 API
curls + email-render procedure + rollback.
Files:
- backend/alembic/versions/0016_denial_decay_and_scope.py (new)
- backend/app/models/__init__.py:221-242, 250-269
- backend/app/schemas/__init__.py:204-219, 248-269
- backend/app/api/meals.py:30-138 (helpers), 240-330 (HTML page),
380-455 (submit_vote), 486-552 (deny_meal_item)
- backend/app/services/orchestrator/steps.py:283-300
- backend/app/services/planner/generate.py:59-99, 150-194
- frontend/src/api/index.ts:48-58
- frontend/src/pages/Dashboard.tsx:38-50, 385-410
- Review/{sprint8-verification,ui-nielsen-audit,handoff-ui-audit}.md
- fix-ui-audit.md
- docs/HANDOFF.md
- .agent/{plan,context}.md
Deploy (user runs on deployment host):
cd ~/MealPlanner && git pull
docker compose exec backend alembic upgrade head
docker compose -f docker-compose.yml up -d --build backend frontend
User report 2026-06-05: 'webui Meal Planner page is empty' on Friday
morning after the Friday email went out. Root cause: the orchestrator
keyed plans by the most-recent-Friday while the frontend's isoMonday()
returned the most-recent-Monday — a 7-day mismatch on Fridays.
Fixes (one semantic across the stack):
- runner._current_week_start() returns the upcoming Monday (today if
Mon, else the next Mon). The Friday email subject
('Meal plan for week of <date>') automatically picks up the new
value via run.week_start_date.
- frontend isoMonday -> upcomingMonday (same logic; renamed for
intent). isoMonday kept as a deprecated alias.
- New WeekRangeNav component (Dashboard + ShoppingList share it).
Renders [<] Jun 8 - Jun 14 [>] with clickable chevrons and a
clickable range label that jumps to the upcoming week. Replaces
the Sprint 5 inline segmented control on both pages.
- New formatWeekRange(mondayIso) helper (UTC-stable; uses
timeZone: 'UTC' so the rendered date matches the stored ISO date
regardless of viewer TZ; closes a latent bug in formatIsoDate too).
- New SQL fix script that retargets the user's 3-pending-items plan
from 2026-06-05 (Friday-keyed) to 2026-06-08 (upcoming Monday).
Idempotent + transaction-wrapped. Optional block for 2026-05-29.
No backend migration. No new dependencies. Deploy is git pull +
run the SQL fix + docker compose up -d --build backend frontend.
See Review/sprint7-verification.md for the full deploy + smoke flow.
Files:
- backend/app/services/orchestrator/runner.py:20-35
- backend/scripts/fix_2026_06_05_to_2026_06_08.sql (new)
- frontend/src/lib/utils.ts:43-130
- frontend/src/components/WeekRangeNav.tsx (new)
- frontend/src/pages/Dashboard.tsx (3 call sites + 1 segmented control)
- frontend/src/pages/ShoppingList.tsx (5 call sites + 2 segmented controls)
- Review/{sprint7-verification,ui-nielsen-audit,handoff-ui-audit}.md
- fix-ui-audit.md
- docs/HANDOFF.md
- .agent/{plan,context}.md
Sprint 6 (F3 + F4) is now documented across the project:
- Review/sprint6-verification.md: new deploy + smoke-check doc.
Backend + frontend deploy (no migration). 5 smoke-check
sections: A) ShoppingList bulk-add end-to-end, B) F3 partial-
failure edge case, C) F4 'Plan the week' button + dropdown,
D) F4 edge cases (no empty slots, all recipes used, invalid
meal_types), E) Sprints 1-5 regression spot-check. Rollback
section covers revert (no migration to undo).
- fix-ui-audit.md: new Sprint 6 section (S6.1 F3, S6.2 F4,
S6.3 verification gate). 'Done when' block updated to 6
sprints / 10 commits / 20 findings closed.
- Review/handoff-ui-audit.md: updated to a 6-sprint cycle. TL;DR
table includes the 8ad4ef6 row. File list includes sprint6-
verification.md. File-level diff summary gains 8 new rows for
Sprint 6 (F3 backend + F4 backend + 3 new schemas + 2 api
bindings + 2 page changes). §Future list now strikethroughs
F3 and F4. Follow-up tickets section added: the no-op
'Generate Meal Plan' empty-state CTA, the (now-narrower) Pantry
bulk-add ticket, and the 'Sprints 2-5 + Sprint 6 separate
batch' deploy note.
- Review/ui-nielsen-audit.md: new Sprint 6 status block at the
top. F3 + F4 documented with the design-decision context
(ShoppingList-only scope; dropdown for All/Dinners; partial-
success with detailed report).
- docs/HANDOFF.md: Last-updated line bumped to 6 sprints / 10
commits / 20 findings / 6 §Future items. Header commit list
gains the 8ad4ef6 row. New 'Sprint 6' subsection in the
2026-06-04 session block. Commit table gained the 8ad4ef6 row.
Files-modified + Files-added lists updated.
No code changes; the 3 pre-existing WIP files (backend/app/api/
recipes.py, schemas/recipe.py, nginx/nginx.conf) are deliberately
not staged.
Sprint 5 (F5 + F2 + 0015 cast fix) is now documented across the project:
- Review/sprint5-verification.md: new deploy + smoke-check doc.
Backend + frontend deploy (one batch with Sprints 2-4). Migration
0015 MUST be run as part of this deploy (the cast fix is what
makes it runnable). 7 smoke-check sections: A) curl tests for
?week_start=, B/C/D) URL week nav on Dashboard and Shopping List
with query-key isolation, E) keyboard shortcut matrix, F) post-
migration canonical-aisle verification query, G) Sprints 1-4
regression spot-check. Rollback section covers reverts + the
persist_aisle_backup recovery path.
- fix-ui-audit.md: new Sprint 5 section (S5.0 critical 0015 fix,
S5.1 F5 implementation, S5.2 F2 implementation, S5.3 verification
gate). 'Done when (overall)' block updated to 5 sprints + 9
commits + 18 findings closed + the 0015 fix unblocks Sprint 2.
- Review/handoff-ui-audit.md: updated to a 5-sprint cycle. TL;DR
table includes the d78bd18 + f740f40 rows with the CRITICAL 0015
fix callout. file-list includes the new sprint5-verification doc.
file-level diff summary gains 16 new rows (S5 backend + frontend +
0015 + hooks/components). §Future list now strikethroughs F2 and
F5. Quick-start deploy commands list Sprints 2-5 as a single
batch (backup → migrate → rebuild backend + frontend).
- Review/ui-nielsen-audit.md: new Sprint 5 status block at the
top. F5 + F2 + the 0015 fix all documented. Cross-ref to
Review/sprint5-verification.md.
- docs/HANDOFF.md: Last-updated line bumped to 5 sprints / 9
commits / 18 findings / with the 0015 fix CRITICAL callout.
Header commit list gains the two Sprint 5 commits. New 'Sprint
5' subsection in the 2026-06-04 session block. Commit table
gained the d78bd18 + f740f40 rows. Files-modified list now
includes all 5 sprints' changes. New 'Files added by Sprint 5'
subsection for the 3 new files in hooks/ + components/.
No code changes; the 3 pre-existing WIP files (backend/app/api/
recipes.py, schemas/recipe.py, nginx/nginx.conf) are deliberately
not staged.
Sprint 4 (F7 + F6) is now documented across the project:
- Review/sprint4-verification.md: new 100-line deploy + smoke-check
doc. Frontend-only deploy (git pull + docker compose up -d --build
frontend). 5 smoke-check tables: A) success toasts still work for
all 11 actions, B) error path shows FastAPI detail (network-down
is the easiest test; full Pydantic 422 verification via curl +
DevTools 'Edit and resend'), C) pre-flight toasts still fire
without a network call, D) plan-status Badge has correct
aria-label in DevTools, E) Sprint 1-3 regression spot-check.
Includes rollback instructions (single-commit revert).
- fix-ui-audit.md: new Sprint 4 section with full per-task notes
(S4.1 F7 implementation details, S4.2 F6 aria-label, S4.3
verification gate). 'Done when (overall)' block updated to 4
sprints + 7 commits + 16 findings closed. No new commit in
fix-ui-audit.md for the F8/F9 §Future addendum (those are noted
in Review/handoff-ui-audit.md but live in the doc/proposals/
tree, not in the UI-audit plan).
- Review/handoff-ui-audit.md: updated to a 4-sprint cycle. TL;DR
table includes the d71b67a row, file-list includes the new
verification doc, file-level diff summary gains 5 new rows for
Sprint 4, §Future list now strikethroughs F6 and F7, and the
Quick-start deploy commands list Sprint 4.
- Review/ui-nielsen-audit.md: new Sprint 4 status block at the
top with the F7/F6 changes, the no-backend-changes note, and
a cross-ref to the new verification log.
- docs/HANDOFF.md: Last-updated line bumped to 4 sprints / 7
commits / 16 findings. New 'Sprint 4' subsection in the
2026-06-03 session block. Commit table gained the d71b67a row.
Files-modified list gained the lib/toast.tsx, App.tsx, and
three pages changes for Sprint 4 (with B-tags preserved).
No code changes; the 5 pre-existing WIP files (backend/app/api/
meals.py, recipes.py, schemas/recipe.py, frontend/src/api/index.ts,
nginx/nginx.conf) are deliberately not staged.
- Update 'Last commits before handoff' list with the four UI-audit
commits (f3e4a44, ccc70aa, f5fb755, e90a9d6) plus the handoff doc
itself (427d8ac) and the docs commit (36038bb).
- Bump handoff date from 2026-05-14 to 2026-06-03 and add a cross-ref
to the focused Review/handoff-ui-audit.md so a fresh agent can
choose which doc to start with.
- New 'Last updated' line summarizes the UI-audit cycle (Sprint 1
deployed; Sprints 2 and 3 awaiting deploy; migration 0015 not yet
run on prod).
- Add a 'New session: 2026-06-03' section with the commit table, the
Sprint 2 deploy commands (including the container-based psql
incantations since the deployment host has no host psql), the
Tailscale dev-vs-deploy gotcha, the .gitignore/lib/ quirk, and the
file-level add/modify summary for the UI-audit work.
- Correct the 'Current open proposals' line under 'Final words' — the
feedback-driven discovery proposal still awaits user approval; it
is NOT implemented and verified.
- Update implementation-plan.md: mark unit conversion complete
- Update HANDOFF.md: add session notes for 2026-05-24 unit conversion
- Update README.md: list Unit Conversion as a feature
Bring docs in line with the post-AM-6 state so a fresh agent can pick
up cleanly without first reconciling stale numbers:
- pytest count: 88/59/31 → 92 across all references
- live scrape: 9,960 rows / 36s → 9,980 rows / 44s (latest run, 2026-05-06)
- migrations applied: 0001-0005 → 0001-0007 in both docs
- verification gate updated with auto-minted JWT detail and the 29,779
ingredient_grocery_match rows produced post-scrape
- "What is real" / Backend: added swiftly_auth.py bullet describing
get_token() / mint_anonymous_token() / cache semantics + the
10,928-item live verification
- file map: added services/swiftly_auth.py, services/matcher.py,
services/planner/, mentioned scraper_service runs matcher post-scrape
- file map: alembic versions 0001 → 0007, tests/ count = 92, marked
config.py as no-longer-carrying SWIFTLY_BEARER_TOKEN
- spec map line for swiftly-token-auto-mint: "next-up" → "Implemented"
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Breaks the auto-mint spec into 6 ordered, sized tasks with an explicit
halt-for-approval boundary at AM-2 (live scrape verification before
removing the env var). Restates the verified prerequisites (config.json
publicly readable; Firebase signUp returns valid JWT with proper headers;
Swiftly accepts the minted token) so a fresh agent doesn't have to
re-discover them.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Discovery: luckysupermarkets.com/config.json is publicly readable and
exposes firebaseApiKey. With proper Origin/Referer headers, Firebase
Identity Toolkit's anonymous-signup REST endpoint mints the same JWT
shape (iss=swiftly-lu-prod, aud=swiftly-lu-prod, anon provider, 3600s
TTL) that Swiftly accepts. Verified end-to-end on 2026-05-06.
This eliminates the manual hourly token-capture toil and supersedes
the seleniumbase-based scripts/refresh_swiftly_token.py (commit
ccfb38a) which had partial UI selector issues.
- New spec: docs/specs/2026-05-06-swiftly-token-auto-mint.md
- HANDOFF.md TL;DR refreshed (Phase 9 shipped); caveat #2 + #3
rewritten to point to the auto-mint redesign; suggested-next-move
reordered to put the redesign first
- ORIENTATION.md env-var section flags SWIFTLY_BEARER_TOKEN as
scheduled-for-removal; "Where to look" lists both specs;
last-updated footer refreshed
Implementation deferred — this commit captures the design and routing
only. Estimated 2-3 hours of focused work to ship per the spec.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Updates ORIENTATION.md and HANDOFF.md to reflect actual state as of
commit 8e89f79: phases 1/2/3/7 complete (verified, not just claimed),
phases 4/5/6/8/9/10/11 not started. Documents the auth model, the
bootstrap login hatch, the SWIFTLY_BEARER_TOKEN expiration handling,
the Swiftly JSON API ingestion path that replaced Playwright, the
canonicalized API paths, and the verification commands to reproduce
the 31/31 pytest gate locally and in CI.
HANDOFF.md is intended for fresh agents and points at .agent/
phase-summaries for the per-phase write-ups. Surfaces 10 caveats and
traps the next agent will hit if they skim, and recommends Phase 9
(meal-planner generation algorithm) as the next move.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>