All documents
Specification

SmartMarket

What the grocery assistant does, and the two things it is actually judged on: how fast it finds something, and whether the money is right.

Document
SRS-SM-1
Version
1.0
Date
31 August 2026
Status
For review
Author
Abad Naseer

1Purpose and scope

SmartMarket takes a shopper's own words, finds the products a shop actually stocks, builds a basket, takes the money, and puts the order into the shop's own database in the shape that shop's existing systems already read. The conversation is the shopfront; everything behind it is ordinary retail plumbing that has to be exactly right.

This document specifies what it is required to do and how it is required to behave. Two things dominate it and neither is the language model. The first is latency, because a shopper abandons a search that takes six seconds. The second is the correctness of money, because an order that reports a tip as sales tax is a bookkeeping problem for somebody else to find months later.

2The system in one picture

A sentence becomes a search, a search becomes a basket, a basket becomes a paid order. The order is written locally first and reaches the shop's own database afterwards, through an outbox, and that ordering is the whole of section 5.3.

“cheapest eggs” Catalogue in memory, 8 ms Cart, tax and tip Paid, and written here Outbox row, pending The shop's database Not stocked? source it

Fig. 1 · from a sentence to a row in the shop's database

3Who uses it

WhoWhat they come for
A shopperA week's groceries, described rather than navigated. Often on a phone, often by voice, often while doing something else.
The shopOrders arriving in its own database, in its own shape, without anybody rekeying them.
The officeWhat was ordered, what was paid, what was sourced from outside the catalogue, and what failed.

4What it does

Finding things

  • F-1Understand a whole sentence, not a keyword. “Cheapest eggs” and “best deal on coffee” are price intents and are ranked as such, not matched as strings.
  • F-2Rank against what the shop stocks, from an index held in memory, without reading the catalogue out of the database for every search.
  • F-3Return results whose ordering is stable, so the same question asked twice does not reshuffle the shelf under the shopper.
  • F-4Where the shop does not stock something, offer to source it from outside the catalogue rather than saying no.

Buying

  • F-5Add, change and remove basket lines from inside the conversation, without leaving it for a separate cart screen.
  • F-6Compute tax on the goods, and a tip on the goods before tax, and show the three numbers separately at every step.
  • F-7Take payment by card or PayPal, and support cash on delivery where the shop offers it.
  • F-8Confirm by email, itemised, with the same three numbers the checkout showed.

Speaking

  • F-9Accept a spoken order and answer aloud, with speech handled on the server so no provider key ever reaches a browser.
  • F-10Continue listening across turns, so a shopper can dictate a list rather than press a button per item.

The office

  • F-11List orders and payments, with what each one actually collected.
  • F-12Show sourcing outcomes, including what was sourced from outside the catalogue and by which provider.

5How it must behave

5.1Search latency

The catalogue barely changes and used to be re-read in full on every single search: roughly 25,600 rows of embedding text pulled out of MySQL, re-parsed and stacked into a fresh matrix, in order to run one dot product that takes microseconds. The loading was the response time. It is now loaded once at startup and held in memory, and a search is a matrix multiply, a threshold and a sort.

QueryBeforeAfterChange
milk6,558 ms6.50 ms1,009x
eggs6,434 ms4.58 ms1,405x
cheese6,428 ms11.11 ms579x
cheapest eggs6,444 ms26.91 ms240x
best deal on coffee6,468 ms27.33 ms237x
Median6,456 ms8.21 ms787x

Two rules governed that change and remain requirements. The results must be identical, which is asserted against the live database by a parity check rather than asserted in prose. And it must be never worse: if the index is missing, still building or switched off, search falls back to the database path silently.

5.2Correctness of money

  • N-1Tax is computed on the goods. The tip is computed on the goods before tax, because tipping a percentage of sales tax is not a thing anybody means to do.
  • N-2The tip percentage is decided on the server from a fixed set of offered values. A percentage arriving from a browser that is not one of them is a client that has been edited, not a shopper being generous.
  • N-3Tax is never derived by subtracting the goods from the total. That is how it was written before tips existed, and left alone it would have reported every tip as sales tax, in the order record and in the confirmation email both.
  • N-4Goods, tax and tip appear as three separate numbers wherever a total appears: the basket, the checkout, the order record and the email.

N-3 is stated as a requirement rather than a fixed bug because it is the kind of fault that is invisible while it is happening. It was found by checking that a $5 tip left the tax at 1.93, not by anything failing.

5.3Getting orders to the shop

Orders are written to this application's own database first, and pushed to the shop's afterwards by a separate process draining an outbox. The shopper's confirmation does not wait on a network hop to somebody else's server, and a shop database that is briefly unreachable delays delivery of an order rather than losing it.

  • N-5An order is complete and confirmed on this side before any attempt to push it. The push is retried and its failures are recorded per row.
  • N-6Local identities are mapped to the shop's identities and the mapping is kept, so a retry updates rather than duplicates.
  • N-7Exactly one machine drains the outbox. This is a requirement rather than a convention: it has been violated three times by cloned machines that came up with the sync running, and each time two machines were writing the same rows into a live shop database.

The check for N-7 is one command and belongs in every handover: the sync must be active on the grocery machine and on no other. Checked by asking each machine, not by assuming.

5.4Fallback

  • N-8Sourcing from outside the catalogue goes through a provider interface. When a provider is unavailable or unconfigured, sourcing degrades and the rest of the shop keeps working.
  • N-9Speech failing in either direction leaves the written path intact. A failed transcription asks the shopper to repeat themselves; a failed voice is read by the browser.
  • N-10A payment provider being unavailable must not create an order that nobody paid for.

5.5Security

  • N-11No provider key reaches a browser. Speech runs on the server specifically because an earlier version called a speech provider from the front end with an exposed key.
  • N-12Prices, tax, tips and totals are computed on the server. Nothing that decides what is charged is taken from the client.
  • N-13Office functions require an admin token.
  • N-14Test and demonstration data must never reach the shop's live database. The sync is stopped before any test that creates orders, and this has already been necessary.

5.6Observability

  • N-15Search timing is logged per query, so a slow answer can be attributed to retrieval or to the engine rather than guessed at.
  • N-16The outbox reports its own state: pending, done, attempts, and the last error per row. A stuck order is a row somebody can look at.
  • N-17Sourcing records which provider answered and what it returned, so an item that arrived from outside the catalogue can be traced.

6Where it runs

PartWhat
Addressmarketz.smartzees.com
ApplicationFastAPI, one process
ScreensNext.js, exported as static files and served by nginx
DatabaseIts own MySQL schema, plus an outbox to the shop's
Catalogue indexAbout 25,600 products, 384 dimensions, held in memory
RegionIts own, separate from the other two agents

It is the only one of the three agents in its region, which means it cannot reach the other two privately and does not need to. It shares nothing with them except the engine switch and the hardware behind it.

7Assumptions and limits

  • A-1The catalogue is the shop's. Products that are missing, mispriced or out of date in it are missing, mispriced or out of date here.
  • A-2The in-memory index assumes a catalogue that changes rarely. It is rebuilt rather than updated in place, and a shop that reprices hourly would need that reconsidered.
  • A-3Sourcing from outside the catalogue depends on a third party, whose availability and terms are outside this system.
  • A-4English only, for the same reason as the other two agents: the retrieval model is an English model.

8Out of scope

Not hereWhy not
Stock levels and reservationsThe shop's own systems own stock. This orders from a catalogue, it does not hold inventory
Delivery routing and driversAn order reaches the shop's database and the shop's existing operation takes it from there
Refunds and returnsHandled by the shop, through the payment provider, outside this application
Community documents and bookingsSeparate products, on separate machines, with separate databases

Written by Abad Naseer. Every measured number in this document is cited from the running system or from the code, and every target says that it is a target. Where the two disagree, the document says so rather than choosing the flattering one.