Skip to main content
Paul Welty, PhD AI, WORK, AND STAYING HUMAN

2026-03-22 — Dinly: two scout passes, post-meal feedback, and the pantry system

What shipped today

The session ran two full /scout passes across the codebase, creating and executing 18 issues in a single continuous session. The first pass (carried from late March 21) identified and fixed security, error handling, and performance issues from the earlier scout. The second pass found a new round of security gaps, a memoization bug, dead code, and missing tests — all executed same-session.

Security hardening. Two rounds of ownership verification landed. The first (#144) added verifyMemberOwnership() to vote and onboarding actions. The second (#161) extended this pattern to family member CRUD (updateFamilyMember, deleteFamilyMember) and all cycle mutation actions (saveCandidates, suggestCandidate, saveCuratedPlan, resolveTypeCandidate). Every server action that accepts a user-supplied resource ID now verifies household ownership before operating.

Error handling and performance. All 13 unchecked Supabase operations across 6 files now destructure { error } and throw on failure (#145). The import batch counting bug was fixed — importedCount no longer increments when ingredient insertion fails. The cron job’s N+1 queries were eliminated (#146) by batch-fetching all family members and votes upfront into lookup maps. Plan finalization’s sequential recipe_history inserts were batched (#147), and two missing database indexes landed (weekly_requests.family_member_id, weekly_votes composite).

Post-meal feedback loop. The complete learning system shipped across 4 issues (#153-156). Migration 011 added recipe_history.skipped and recipe_bookmarks.meal_plan_entry_id. The finalized cycle page now shows a “How was your week?” card where each family member can mark meals as ate/skipped and rate them 1-5 stars. The ranking engine gained a new bookmark_tried_positive/negative dimension that boosts recipes rated 4-5 and penalizes those rated 1-2. A daily cron nudge email goes out the day after a week ends, prompting families to review their meals.

Pantry/inventory system. The complete pantry feature shipped across 4 issues (#170-173). Migration 012 created the pantry_items table with household-scoped RLS. A new /pantry page (cook-level) provides CRUD with autocomplete from recipe ingredients. Shopping lists now show an “in pantry” badge for items matching pantry ingredients. The ranking engine gained a pantry_match_high/medium dimension — recipes with 75%+ ingredients in pantry get +3, 50-74% get +1.

Code quality. Dead code was cleaned up (#163): notifyShoppingList, shoppingListEmail, badge(), recipeList(), unused imports and variables — 64 lines deleted. The RecipeSearch memoization bug (#162) was fixed — missing dependencies (dateFilter, mealTypeFilter, bookmarkFilter) caused stale filter results; a useMemo side effect was replaced with proper useEffect. Unit tests were added for isPrimaryCook, isAdmin, addDays, getNextMonday, and formatDateRange (#164), bringing coverage from 38 to 65 tests.

Completed

  • #144 Add ownership verification for familyMemberId in vote and onboarding actions
  • #145 Add error checking on Supabase delete/insert operations in server actions
  • #146 Batch cron job queries to eliminate N+1 pattern
  • #147 Batch plan finalization inserts and add missing database indexes
  • #148 Design post-meal feedback loop (decomposed into #153-156)
  • #153 Add meal feedback schema: skipped flag and meal_plan_entry_id on bookmarks
  • #154 Add meal feedback UI to finalized cycle page
  • #155 Add tried-rating scoring dimension to ranking engine
  • #156 Add post-week feedback nudge email
  • #161 Add ownership verification to family CRUD and cycle mutation actions
  • #162 Fix RecipeSearch memoization bug: stale filter results
  • #163 Remove dead code: notifyShoppingList, unused imports, orphaned helpers
  • #164 Add unit tests for auth helpers and date utilities
  • #165 Design pantry/inventory system (decomposed into #170-173)
  • #170 Add pantry_items table with RLS
  • #171 Add pantry management page with CRUD and navigation link
  • #172 Show “in pantry” indicators on shopping list items
  • #173 Add pantry match scoring dimension to ranking engine

Release progress

  • March 2026: 6/6 closed (complete)
  • Phase 1–4: all closed

Carry-over

  • DECISIONS.md has uncommitted local changes (design decisions for feedback and pantry features)
  • The full planning flow (Draft → Vote → Curate → Resolve → Days → Shopping) still has not been tested end-to-end in the browser with real data — carry-over since March 19
  • Set CRON_SECRET env var in Vercel for the cadence cron job — carry-over since March 20
  • Verify email notifications fire correctly with real auth flow
  • Deploy to production and verify the new features render (feedback section, pantry page, shopping list badges)

Risks

  • The pantry page’s autocomplete fetches up to 5,000 recipe_ingredients for normalization suggestions. For households with very large recipe libraries, this could become slow — may need server-side search or limit.
  • The feedback nudge email triggers for ALL finalized cycles where today === addDays(week_end_date, 1). If old finalized cycles exist with past week_end_dates that happen to match rollover, they could get spurious nudges. In practice this is unlikely since the date comparison is exact, but worth noting.
  • 65 tests now exist but server actions (the bulk of the app’s mutation logic) remain untested — only pure functions are covered.

Flags and watch-outs

  • 17 commits landed today — largest single-session output for Dinly
  • Test count: 33 → 65 (nearly doubled)
  • Two new Supabase migrations applied: 011 (meal_feedback) and 012 (pantry)
  • DECISIONS.md has two new entries: post-meal feedback storage approach and pantry MVP design decisions
  • Issue queue is now empty — no open issues
  • The pantry feature completes the “what’s already in the pantry” part of the product vision
  • The feedback loop completes the “learn from what the family actually eats” part of the product vision

Why customer tools are organized wrong

This article reveals a fundamental flaw in how customer support tools are designed—organizing by interaction type instead of by customer—and explains why this fragmentation wastes time and obscures the full picture you need to help users effectively.

Infrastructure shapes thought

The tools you build determine what kinds of thinking become possible. On infrastructure, friction, and building deliberately for thought rather than just throughput.

Server-side dashboard architecture: Why moving data fetching off the browser changes everything

How choosing server-side rendering solved security, CORS, and credential management problems I didn't know I had.

The work of being available now

A book on AI, judgment, and staying human at work.

The practice of work in progress

Practical essays on how work actually gets done.

When your agents start breaking each other's code

Two agents modified the same file independently and created database locks. The fleet hit 135 issues in one day — and the coordination problem that comes with it.

The removal tax

The most productive thing you can do with a product is take features away. Eighty-nine issues closed across eight projects, and the hardest lesson came from a pipeline that ran perfectly and produced nothing.

The product changed its mind

A product pivoted its entire philosophy mid-session — from 'here's your list' to 'here's your next thing.' The code shipped in the same conversation as the idea. That's not iteration. That's something else.