From ad087df5cbeb8d1cd4791c3c68f8feaca2d23e69 Mon Sep 17 00:00:00 2001 From: OpenClaw Bot Date: Tue, 12 May 2026 18:46:40 +0200 Subject: [PATCH] docs: consolidate meal planning roadmap --- docs/MEAL_PLANNING_ROADMAP.md | 109 +++++++++++++++++++ tests/e2e/oikos-kitchen-assist-flow.spec.mjs | 3 + 2 files changed, 112 insertions(+) create mode 100644 docs/MEAL_PLANNING_ROADMAP.md diff --git a/docs/MEAL_PLANNING_ROADMAP.md b/docs/MEAL_PLANNING_ROADMAP.md new file mode 100644 index 0000000..cf53a2b --- /dev/null +++ b/docs/MEAL_PLANNING_ROADMAP.md @@ -0,0 +1,109 @@ +# Oikos Meal Planning — Combined Roadmap + +Status: active Friborg branch roadmap. This merges the older Assist plan, native meal-planning patch notes, structured taxonomy work, Playwright E2E plan, and upstream-readiness backlog into one source of truth. + +## North Star + +Meal planning should be a native Oikos kitchen workflow, not a chatbot shortcut. Assist can suggest and prefill, but the family reviews and edits in a dedicated Kitchen surface before anything is written. + +## Current Verified Live Baseline + +- Public app: `https://home.friborg.uk` +- Core branch: `friborg/native-meal-planning` +- Latest verified core commit: `58a76ee` (`feat: structure meal planning taxonomy and favorites`) +- Latest verified Assist/Studio commit: `062211f` (`chore: remove legacy meal plan add path`) +- Live core image: `oikos-structured-mealflow:20260512-170557` +- DB schema: migration `41` +- Latest live E2E: `OIKOS_E2E_MUTATE=1 npm run test:e2e:oikos-flow -- --project=chromium-desktop` → 2/2 passed, cleanup zero + +## Completed Plan Threads + +### Studio-first Assist handoff + +- [x] Meal-plan prompts return a structured `studioPlan` instead of text-only drafts. +- [x] Assist action card opens the page-level Kitchen Studio. +- [x] Direct legacy text-plan add path removed from the widget. +- [x] Studio lives on `/meals` as a Kitchen module. +- [x] Confirming the Studio writes native meals through explicit user action. + +### Native meal-planning data + +- [x] Native `/api/v1/meal-planning/*` endpoints for rules, recipe signals, variation metadata, cook assignments, feedback, and kids cookbooks. +- [x] Native `/api/v1/meals` accepts and returns cook assignments. +- [x] Meal/recipe taxonomy promoted into core fields: `meal_category`, `protein`, `style`, recipe `tags_json`. +- [x] Leftovers are first-class via `leftover_from_meal_id`. +- [x] `source_plan_id` preserves Studio provenance. + +### Family preference and learning loop + +- [x] Likes/dislikes/favorite/can-cook/can-help/modified-ok/adult-only signals. +- [x] Meal modal and recipe cards can save person-specific signals. +- [x] Family profile cards report favorite and can-cook counts. +- [x] Accept/reject/edit/swap/confirm feedback is recorded. +- [x] Learning summary panel exposes signal counts. + +### Planning quality + +- [x] Planner considers family rules, cook assignments, preferences, weather/activity/season context. +- [x] Generation modulators are explicit in Studio plans: season, weather, easy/busy days, guests, no-kids/adult-only context, family favorites/likes/dislikes, child age, child can-cook/can-help signals, and variety counters. +- [x] Planner tracks category/protein/style diversity. +- [x] Adjacent category repeats are penalized/avoided. +- [x] Swap alternatives are ordered to preserve diversity constraints. +- [x] Leftovers are dedicated linked slots, not note text. + +### Kids flow + +- [x] Kids board with large category cards. +- [x] Drag/tap meal card assignment to days. +- [x] Kid cookbook preview and saved cookbook storage. + +### Verification and safety + +- [x] Playwright smoke covers Kitchen open + Assist handoff. +- [x] Mutating E2E covers swap/edit/confirm/native readback/cook assignments/cleanup. +- [x] Structural E2E asserts categories, diversity, linked leftovers, favorite-signal UI, profile count reflection, and cleanup. +- [x] Structural E2E asserts Studio plans expose modulator labels and active signal types, so planning context is not hidden in opaque AI text. +- [x] Playwright artifacts are opt-in to reduce credential leak risk. + +## Remaining Combined Plan + +### P0 — Upstream/Core polish before PR + +- [ ] Make OpenAPI more explicit for meal-planning request/response bodies instead of broad `object` bodies. +- [ ] Update product spec data model to include native meal-planning tables and structured meal/recipe taxonomy. +- [ ] Keep Friborg-specific deployment details out of upstream docs/PR copy. +- [ ] Rebase `friborg/native-meal-planning` onto current upstream `main` and resolve conflicts. +- [ ] Prepare small upstreamable PR slices rather than one giant Friborg branch. + +### P1 — Reduce sidecar ownership + +- [ ] Keep moving UI state from injected Assist widget toward native Kitchen components. +- [ ] Preserve Assist as suggestion/provider layer, not system-of-record. +- [ ] Add native Studio API boundaries where useful before porting the full Studio UI. +- [ ] Keep Settings → Assist limited to provider/model plumbing. + +### P1 — UX polish + +- [ ] Localize new structured meal fields and preference labels fully (currently several labels are English in Danish/German UI surfaces). +- [ ] Make leftovers source selector easier to scan by week/date/category. +- [ ] Add small visual category chips consistently across meals, recipes, and Studio. +- [ ] Add dedicated Studio controls for one-off guests/no-kids/easy-day overrides instead of relying only on activity/event text detection. +- [ ] Improve mobile layout for Studio slots and kids board after the data model has stabilized. + +### P2 — Platform modularization + +- [ ] Module registry for routes/navigation/capabilities. +- [ ] Locale registry so supported locales, picker labels, and service worker precache come from one source. +- [ ] Extension/overlay mechanism for deployment-specific customizations without patching core. + +## Implementation Rule + +Continue in verified slices: + +1. make the smallest meaningful change, +2. run syntax/unit gates, +3. deploy only when needed, +4. run live smoke/E2E when the public flow changes, +5. verify cleanup/data health, +6. commit and push to Gitea, +7. update this roadmap if scope or status changes. diff --git a/tests/e2e/oikos-kitchen-assist-flow.spec.mjs b/tests/e2e/oikos-kitchen-assist-flow.spec.mjs index 1fa71b5..7ec6ec1 100644 --- a/tests/e2e/oikos-kitchen-assist-flow.spec.mjs +++ b/tests/e2e/oikos-kitchen-assist-flow.spec.mjs @@ -77,6 +77,9 @@ function assertStructuredStudioPlan(plan) { const leftovers = plan.slots.filter((slot) => (slot.meal_category || slot.variation?.category) === 'leftovers' || slot.leftover_from_meal_id); expect(leftovers.length, 'leftovers should be represented as a dedicated structured option when meal history exists').toBeGreaterThanOrEqual(1); expect(leftovers.every((slot) => slot.leftover_from_meal_id || slot.context?.leftoverSource?.id), 'leftover slots should link to a source dish id').toBeTruthy(); + expect(plan.modulators?.activeSignalTypes || [], 'planner should declare the family-signal modulators it scores against').toEqual(expect.arrayContaining(['favorites', 'canCook', 'adultOnly'])); + expect(plan.slots.every((slot) => Array.isArray(slot.context?.modulators?.labels) && slot.context.modulators.labels.length >= 3), 'each Studio slot should expose generation modulators, not just a chosen recipe').toBeTruthy(); + expect(plan.slots.some((slot) => slot.context?.modulators?.easyDay || slot.context?.modulators?.guests || slot.context?.modulators?.noKids || typeof slot.context?.modulators?.cookAge === 'number'), 'generated week should carry actionable day/person modulators').toBeTruthy(); } async function deleteMeals(page, mealIds) {