Your Chatbot Verified the Price, Then Pasted It Into a Sentence It Wrote
The retrieval was right, the verification was right, and the customer still read a stale price. The bug was the line that patched the number into the model's sentence.

Search for a command to run...
The retrieval was right, the verification was right, and the customer still read a stale price. The bug was the line that patched the number into the model's sentence.

I assumed one billable operation per message. A week of instrumented runs said four, and that single number moved the payback from 200 months to 14.

Three providers differ in exactly three places, and each one fails without an error. A tested router, a price registry, and a ledger row per call.

Date-versioned rules, an entry id derived from the facts, and an append-only ledger: the Apps Script pattern that turns a recompute into a no-op.

CacheService caps out at six hours and can drop entries before they expire. This is the session design that survives both, with the code and the assertions behind it.

Owning the source and owning the running system are different things. Four of the five facts that decide it are not in the code you were handed.

Why searchCriteria[currentPage] loses rows on a live store, the keyset cursor that replaces it, and the four documentation traps that cost real orders.

The per-model minimum prefix, the Apps Script bytes that invalidate it, and the one log line that turns a silent miss into a visible bug.

The availability math, the read-then-write race that double-books you, and the guards a public web app needs — with the full code.
