How Wally refines the vertical (Arrival board)

The Arrival board's first frame is painted by a deterministic keyword classifier (src/lib/arrival.ts) — that's the "Looks like a Restaurant (matched bar, brunch)" header you see within 200 milliseconds. In parallel, Wally fires a second-opinion LLM classification. If Wally disagrees, the lanes re-flow to its pick and a "Wally refined" chip appears in the header.

Why two passes:

The keyword pass is cheap, deterministic, and offline. It guarantees a non-empty first frame even if the wally domain service is unreachable. The LLM pass is smarter — it handles cases the keyword list misses ("artisanal cheese cave + cellar door tasting room" → Restaurant, not the Other fallback the keyword classifier would land on) and overrides ambiguous cases where the keywords stutter ("dive bar near the dive shop" → Restaurant, not Outdoor).

The contract:

• **Input**: { description: string } — your free-text describe-it copy.
• **Output**: { vertical, reasoning, source: 'wally' | 'fallback' } — vertical is one of the 11 TemplateCategory values; reasoning is a one-liner you can read by hovering the chip; source flips to 'fallback' if Anthropic was unreachable.
• **Model**: claude-haiku-4-5-20251001 — small, fast, JSON-mode prompt with a hard-coded vertical list it can't deviate from.
• **Auth**: signed-in user, no orgId required (you're pre-org).

What "Wally refined" means in practice:

When the chip appears, the Starter Site / Module Fit / Neighborhood lanes have already re-flowed to Wally's pick. URL/domain extraction (which is regex-based and not LLM-dependent) stays. Your toggle choices on the previous vertical are reset — a vertical flip is a structural change to what the lanes are showing.

What if Wally is wrong?

Wally being wrong about your vertical means the lanes show templates and modules that don't fit. The fix is to expand your description with a clearer signal ("…full-service restaurant" or "…vacation rental property"). The classifier picks the highest-confidence keyword cluster, so adding a couple of unambiguous words usually flips it.

What if the wally domain isn't deployed?

The client gracefully holds the keyword classifier's result. The "Wally refined" chip never appears; users still get useful onboarding. This is intentional — the wally domain is a Cloud Run service we cut over per-environment via a build-time env var (VITE_DOMAIN_WALLY_URL). Production has it enabled; preview environments may not.

Cost:

Each classification call is roughly 500 input + 100 output tokens of Haiku 4.5 — fractions of a cent per onboarding. Not cached today (cache key would be the description string but at this volume the cache hit rate is too low to be worth it).