Data-layer work on the assistant, in the order it mattered.
Correctness first:
- getBookingsPage keeps the envelope's `total`/`page`. getBookings threw
them away, so no caller could tell a full result from a truncated one.
- Every booking read now drains pages up to a budget instead of taking page
one at the API's 1000-row cap. Past 1000 lifetime bookings, every count
and sum in this file silently under-reported while the source line beside
it still read "complete". Row order is detected per call, so a backend
that stops returning newest-first degrades to a full scan rather than to
a wrong answer.
- A capped scan now says "At least N", appends what it scanned versus the
total, and marks its source call as failed.
- Revenue excludes cancelled orders, sums every service option rather than
the first, and is labelled estimated — it is a quote, not settled money.
- A strong order reference that isn't found is answered "I couldn't find
it" instead of falling through to a broader intent, which used to answer
"142 orders created today" to a question about one order.
Then agreement with the Orders page:
- utils/orderStatusGroups.js is now the single definition of which raw
booking enums make up each status; orders.js builds its tabs from it and
the assistant matches against it. The assistant had been using api.js's
Deliveries taxonomy, which keeps miler_assigned on `pending`, so the
Orders page showed 19 Assigned while the bot answered 0. The two
taxonomies stay separate on purpose — Orders tracks the operator's
action, Deliveries tracks the rider's.
- A status question with no date named is no longer scoped to today. "How
many orders are assigned" describes the queue right now, which is what
the Orders page's tabs show; they apply no date filter either.
- The Orders header said "Today" over counts that were never date-filtered.
Corrected the label rather than adding a filter, since filtering would
hide currently-visible rows — a product decision, not a bug fix.
Then capability:
- delayedOrders answers "which orders are delayed" from the promised
delivery time. deliveries.js and Dispatch.js both rejected that field for
batch bucketing because an ETA is not the wave an order belongs to; that
reasoning does not carry over to lateness, where a promise that never
gets re-stamped is exactly the right baseline. If no order carries an
ETA it says so rather than reporting a reassuring "0 delayed".
- orderQuery composes status x batch x tenant x rider, plus rankings. It
claims a question only when two or more of those are present, so
single-dimension questions keep their proven intents. A date is not
counted as a dimension — counting it re-routed four working questions.
- An unresolved tenant/rider name falls through instead of having its
filter silently dropped, which was the original defect.
- orderLookup resolves the rider's name and reads the tracking trail
defensively, since that endpoint's response shape is undocumented.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>