The happy path is not a scope
Discovery notes love the sunny route — order placed, webhook received, ticket printed. Production work lives in the late webhook, the rejected print job, the unparseable line, and the second click. If those paths are not in the scope, the estimate is for a demo.
What most scopes actually describe
A typical discovery write-up walks the sunny route. An order is placed. The webhook arrives. The ticket prints. The editor publishes a page. The customer sees the right price. Those steps matter, and they are also the part everybody can picture in the workshop without friction.
What is missing is almost always the same: what the system does when the webhook is late, when the printer rejects the job, when OCR cannot place a line, when the catalog says the SKU does not exist, when a second click arrives before the first write finishes. Those are not edge cases in the cute sense. They are the operating conditions of every integration we ship.
If the scope document only certifies the sunny route, the estimate is for a demo. The production system still has to be built — it just was not named, so it was not scheduled.
Name the refusal before you name the feature
For every seam we put in a quote, we ask what the product is allowed to do when it cannot finish the job. Retry silently. Surface a queue for a human. Refuse the action and leave the upstream system unchanged. Drop the event and alert. Those are different products with different costs.
On Al's Flowers, a print job that was never accepted by the print service can be retried. A job the service already accepted cannot be blindly resent, because a retry there is a duplicate ticket on the bench. That distinction is not an implementation detail we discovered in week six. It is a scoping answer: acceptance by the printer is its own state, and retries are keyed to that state.
On document work, the same question splits the pipeline. Some OCR failures are repairable against an authoritative catalog. Others are guesses about what a buyer meant. Repairable failures become recovery passes. Guesses become a human review item with the specific problem stated. If you leave that split unsaid, engineers invent a heuristic in the middle of the build, and you inherit silent wrong data.
Acceptance criteria that survive a bad day
We write acceptance so a reviewer can fail the deliverable without arguing about taste. "Orders become tickets" is a wish. "A Shopify order webhook creates exactly one operational record keyed by order ID; a duplicate delivery of the same webhook does not create a second ticket; a missed webhook is closed by a reconciliation pull within the agreed window" is a contract.
The negative cases belong in the same list, not in a footnote. Invalid auth returns a structured error without leaking whether the account exists. An empty CMS field falls back to a defined default instead of blanking the page. A long-running iOS sync that loses its background window resumes from a durable unit instead of restarting from zero. If those sentences are not in the criteria, they will be negotiated later under schedule pressure, which is when teams ship the optimistic path and call it done.
A useful test in the scoping call: for each must-have flow, ask what a correct failure looks like. If nobody can answer in one sentence, the flow is not scoped yet.
How this changes the estimate without changing the ambition
Scoping failure paths does not mean building every recovery mode on day one. It means deciding which failures are in the first release, which are logged and handled manually, and which are explicit non-goals. Manual handling is a valid product choice when the volume is low and the cost of automation is high — but only if someone owns the queue and the SLA is written down.
Where we cut is usually obvious once the refusals are named. The workshop wanted "AI extracts every line from every vendor PDF." The scoped version is "the system extracts what it can prove against the catalog, queues the rest with a reason, and never invents a SKU." Same ambition on the happy cases. Far less fiction on the rest.
The seam spike still matters for unknown APIs and devices. This note is the complementary habit: even when the seam is familiar, the quote has to price the paths where the seam says no.
What we put in the scoping notes now
For each must-have flow we capture four lines: the success condition, the authoritative system of record, the refusal or recovery behavior, and how a duplicate or late event is handled. That is enough to keep the sunny-route story from pretending to be the whole job.
We also write the non-goals next to them. "No automatic reprint after printer acceptance" is as useful as "ticket prints on order." Non-goals stop a reasonable-sounding follow-up request from looking like a missed requirement.
If a stakeholder only wants the happy path written down, we still write the failure paths ourselves before we agree to a schedule. The alternative is discovering the real product in QA, when the calendar is already spoken for.