2026-03-23 — Dinly: third scout pass, quality hardening, and production readiness
What shipped today
The session continued from the March 22 rollover with the issue queue empty. Two scout passes ran back-to-back, identifying and shipping 18 more issues across security, performance, UX, tests, dead code, and deployment readiness. The codebase went through 4 total scout passes (28 parallel scans) over the two-day session, bringing it from “functional but rough” to production-quality.
Security and input validation. The second round of hardening landed: HTML injection in invite emails was fixed by escaping household names with a new escapeHtml() helper (#178). Feedback rating validation now rejects non-integer or out-of-range values before hitting the database (#178). Pantry ingredient names are capped at 200 characters (#178). Recipe time fields (prep, cook, total) now clamp to 0-1440 minutes — no more negative or absurdly large values (#190). Household names validate 1-100 characters with trim (#190).
Performance. The plan page’s 3 redundant family_member queries were deduplicated (#188) — member IDs are now fetched once and reused across dietary_rules, ingredient_preferences, and dish_preferences queries, eliminating 2 unnecessary roundtrips. The pantry autocomplete was scoped to household recipes with a reduced 2000-row limit (#191), down from 5000 unscoped rows.
UX. The onboarding wizard finally displays errors instead of silently swallowing them (#189) — failed saves now show a red alert and prevent advancing to the next step. The household settings form gained “Saving…”/“Saved” feedback via a new HouseholdSettingsForm client component (#180). All icon-only buttons across the app now have aria-labels for screen reader accessibility (#180).
Tests. 10 unit tests were added for the ingredient parser (#179) covering fractions, mixed numbers, ranges, parenthetical notes, comma-separated notes, decimals, and name normalization. Test count: 65 → 75.
Dead code and deployment. Unused Card imports were cleaned from vote/page.tsx and plan-builder.tsx (#181). Critically, proxy.ts was correctly identified as NOT dead code — it’s the Next.js 16 middleware entry point (confirmed by build output showing “ƒ Proxy (Middleware)”). The .env.example was created documenting all 7 required environment variables (#182). CRON_SECRET was set in Vercel production after authenticating the CLI.
AI suggestions prep. The last major vision gap — “AI assists with suggestions” — was filed as #192 and labeled needs-clarification. It requires Paul’s input on LLM choice, budget, MVP scope, and rate limiting before decomposition.
Completed
- #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
- #178 Add input validation: sanitize email HTML, validate rating range, limit string lengths
- #179 Add unit tests for ingredient parser
- #180 Add success feedback to settings form and aria-labels to icon buttons
- #181 Remove unused Card imports from vote page and plan builder
- #182 Set CRON_SECRET in Vercel and create .env.example
- #188 Deduplicate family member queries on plan page
- #189 Display errors in onboarding wizard instead of silently swallowing
- #190 Add bounds validation on recipe time fields and household name length
- #191 Scope pantry autocomplete query to household and reduce payload
Release progress
- March 2026: 6/6 closed (complete)
- Phase 1–4: all closed
Carry-over
- #192 Design AI-assisted recipe suggestions — needs Paul’s input on LLM choice, budget, and MVP scope
- The full planning flow still has not been tested end-to-end in the browser with real data — carry-over since March 19
- Verify email notifications fire correctly with a real auth flow
- Deploy to production and verify new features render (pantry page, feedback section, shopping list pantry badges)
Risks
- The admin households page still has an N+1 pattern (3 queries per household in a loop). Low traffic makes this acceptable for now, but will need batching if household count grows.
- proxy.ts was nearly deleted by a scout scan that misidentified it as dead code. The DECISIONS.md entry about Next.js 16’s proxy export prevented the mistake — institutional memory working as intended.
Flags and watch-outs
- 10 commits landed on March 23 (18 issues closed across the two-day session)
- Test count: 65 → 75 (10 ingredient parser tests added)
- CRON_SECRET is now set in Vercel production — cron job should authenticate on next deployment
- .env.example created with all 7 required vars
- Issue queue is effectively empty — only #192 (needs-clarification) remains
- 4 of 5 product vision items are now implemented: weekly planning ✓, preferences/dietary ✓, pantry ✓, feedback/learning ✓. Only “AI assists” remains.
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 the queue goes empty
Most products don't fail at building. They fail at the handoff between building and becoming real. What happens when the code is done and the only things left are judgment calls?
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.