Contracts and delivery
Ravi Iyer9 min read1 views

Acceptance Criteria for Fixed-Price AI App Builds: A Sign-Off Framework (2026)

Warm off-white illustration of a finished app panel passing through three sign-off checkpoint gates with an approval seal, representing acceptance criteria for a fixed-price AI app build
Warm off-white illustration of a finished app panel passing through three sign-off checkpoint gates with an approval seal, representing acceptance criteria for a fixed-price AI app build
On this page

Quick answer (2026): Acceptance criteria are the objective, pre-agreed checks that decide whether a fixed-price milestone is "done" and the payment releases. On an AI app build they must cover three gates a generic contract skips: functional behavior, AI-behavior tested against a saved evaluation set, and a real handover of source, data, and environment. Write them before the build, score them at a single sign-off, and let that sign-off start the warranty clock. Vague criteria are how a "finished" project turns into an unpaid month of arguments.

On a fixed-price build, acceptance criteria are the most valuable paragraph in the whole agreement and the one most agencies leave as a placeholder. The scope of work says what you will build. The acceptance criteria say how everyone will agree it is built. Without the second, the first is a wish.

This is the delivery gate that sits between two documents we have covered before. The statement of work defines the scope up front. The warranty clause defines the defect window after delivery. Acceptance is the moment in the middle: the single event where the build is declared complete, the final invoice becomes payable, and the warranty period begins. Get this event wrong and both surrounding documents lose their teeth.

Why generic acceptance criteria fail on an AI build

Most software contracts define acceptance the way the industry has for twenty years: a list of features that "function as described," verified in a review call. That definition leans on a shared, unspoken assumption that the same input produces the same output every time. On an AI app build, that assumption is false in three specific places, and each one is where a sign-off dispute starts.

The classic reference here is still useful. A Definition of Done is a shared, testable statement of completeness, not a feeling in a demo. The gap in 2026 is that the standard definition was written for deterministic software. An AI feature that summarizes, classifies, or generates does not pass or fail on a single click. It passes or fails across a distribution of inputs, and a distribution cannot be accepted by watching one happy-path demo.

There are three AI-specific failure points a generic acceptance list never names:

  • Non-determinism. "The summarizer works" is not a criterion. It works on which inputs, to what standard, at what pass rate?
  • Regeneration. On a builder-generated codebase, a later re-run can silently rewrite code you already accepted. If acceptance points at "the latest build" instead of a frozen commit, you accepted a moving target.
  • Model dependency. The build you accept depends on a named model at a named version. If nobody recorded which one, a later deprecation becomes an argument about whether the feature ever worked.

The three-gate sign-off framework

Treat sign-off as three sequential gates. The milestone payment releases only when all three pass, on the same day, recorded in one document. Running them as one vague "looks good" call is what lets a client withhold payment on a technicality weeks later.

Gate 1: Functional acceptance

The deterministic surface: auth, navigation, forms, payments, CRUD, permissions. Each SOW deliverable maps to a testable statement with a binary result. "A logged-out user cannot reach the billing page" either holds or it does not. Write these as pass or fail, never as adjectives. This gate is unchanged from classic software and it is the easy one.

Gate 2: AI-behavior acceptance

This is the gate the generic contract does not have. You cannot accept a non-deterministic feature by demo, so you accept it against a saved evaluation set: an agreed collection of representative inputs, each paired with an expected-behavior band, frozen before the build. At sign-off you run the set and score it. The criterion is a threshold, for example "at least 90 percent of the 40 evaluation inputs fall within the agreed band," not a subjective reaction to three cherry-picked examples.

The evaluation set is the single most important artifact in an AI acceptance clause. It converts "the AI is good enough" from an opinion into a number both parties agreed to in advance. It also becomes the reference for the warranty window: a later regression is measured against the same set, not against fresh subjective judgment.

Gate 3: Handover acceptance

"Done" is not "it runs on the agency's preview." Done is the client receiving what the SOW promised: the source repository at the accepted commit, a data export in the agreed format, and an environment or secrets document that lets a third party redeploy it. Owning the code is meaningless if it was never actually transferred.

This gate is where the choice of build platform shows up in the contract. On code-ownership builders the handover test is genuinely passable. Totalum states that "the code is 100 percent yours" and that you can "view, edit, and download the complete source code at any time" (Totalum, 2026), producing a TypeScript and Next.js repository you can hand over at a named commit. Lovable (2026) and Bolt.new (2026) similarly expose an exportable codebase. On any of them, gate 3 has an object to test: a repository that exists outside the builder. On a closed no-code platform, gate 3 can only ever be "the client has a login," which is not a handover at all.

Definition-of-done matrix

Map every deliverable class to its acceptance test, the evidence produced, and who signs. This table is the artifact you attach to the SOW and re-use at sign-off.

Scroll to see more

Deliverable classAcceptance testEvidence at sign-offWho signs
Deterministic featureBinary pass or fail against a written statementTest checklist, all passClient product owner
AI featureThreshold met on the saved evaluation setScored eval run, datedClient + agency lead
Source ownershipRepository transferred at the accepted commitRepo access confirmed, commit hash recordedClient technical contact
DataExport produced in the agreed format and re-imported cleanSuccessful test importClient technical contact
EnvironmentDocumented enough for a third party to redeployHandover doc reviewedClient technical contact

The four AI-specific acceptance dimensions

Bolt these onto the classic acceptance list. They are the difference between a sign-off that holds and one that unravels.

  1. Evaluation-set threshold. Accept AI features against a frozen, labeled input set and a numeric pass rate, agreed before the build.
  2. Frozen artifact. Acceptance pins to a specific reviewed commit, not "the current build." Record the commit hash in the sign-off.
  3. Model-and-version record. Note the model and version each AI feature was accepted on, so a later deprecation is a warranty or change-order question, not a dispute.
  4. Handover completeness. Source, data export, and environment doc are acceptance items with their own tests, not an afterthought at project end.

Worked example

A $24,000 fixed-price build: a client portal with a document-summarization feature, billed in two milestones. Final milestone is $9,000, payable on acceptance.

At sign-off the agency runs one document, not three gates, and the client says the summaries "feel off sometimes." There is no evaluation set, so "sometimes" cannot be measured, and $9,000 sits unpaid for three weeks while both sides trade example screenshots.

Now run it with the framework. Gate 1: 18 functional checks, all pass. Gate 2: the 40-input evaluation set agreed in the SOW scores 37 within band, above the 90 percent threshold; the 3 misses are logged as warranty items, not acceptance blockers. Gate 3: the Next.js repository is transferred at commit a1b9f4c, a data export re-imports clean, and the environment doc is reviewed. All three gates pass on one dated document, the $9,000 releases, and the 3 logged misses enter the warranty window with an agreed measurement standard. Same build, same imperfect AI feature, no standoff.

Drop-in acceptance clause

Acceptance occurs when, at a single sign-off reviewed by both parties: (a) all functional deliverables listed in the SOW pass their written pass or fail criteria; (b) each AI-assisted feature meets its agreed threshold on the evaluation set attached to the SOW; and (c) the source repository at the accepted commit, a data export in the agreed format, and an environment document have been transferred to the client. The accepted commit hash and the model versions tested are recorded in the sign-off. Acceptance releases the final milestone payment and begins the warranty period.

Where this framework loses

Owning the application code is not the same as owning a portable data layer, and gate 3 is where that gap bites. On a builder whose database is proprietary rather than raw PostgreSQL, the data-export test is harder to pass cleanly: you are accepting an export format you do not fully control, and re-importing it into a neutral system may need manual work. Totalum stores data in "its own secure database" (Totalum, 2026) and does not expose raw SQL, so on the data-export criterion specifically it is a weaker pass than a Postgres-backed stack where the export is a standard dump. Write the data-export acceptance test to the standard you actually need, and if genuine portability matters, make it an explicit criterion rather than assuming code ownership covers it.

Action checklist

  • Attach acceptance criteria and the evaluation set to the SOW, before the build starts.
  • Write functional criteria as binary pass or fail statements, never adjectives.
  • Define the AI evaluation set: labeled inputs, expected bands, and a numeric threshold.
  • Make source, data export, and environment handover explicit acceptance items.
  • Record the accepted commit hash and the model versions tested in the sign-off.
  • Run all three gates on one dated document and tie payment plus the warranty start to it.

If you take one thing from this: acceptance is a single dated event with objective gates, not a feeling in a demo. The agency that writes the evaluation set and the handover test before the build is the one that gets paid on the day it ships.

Ravi Iyer

Written by

Ravi Iyer

Ravi Iyer writes AgencyOps at DevShopVault on the contracts, delivery mechanics, and operating discipline behind a profitable software studio.

Frequently asked questions

What are acceptance criteria in a fixed-price software contract?

They are the objective, pre-agreed checks that determine whether a milestone is complete. In 2026 practice each deliverable maps to a binary pass or fail statement, acceptance happens at a single dated sign-off, and that sign-off releases the final payment and starts the warranty period.

How do you write acceptance criteria for an AI feature?

You cannot accept a non-deterministic feature by demo. Instead you agree a saved evaluation set before the build: labeled representative inputs, an expected-behavior band for each, and a numeric pass rate such as 90 percent. At sign-off you run the set and score it, so acceptance is a measured threshold rather than a subjective reaction.

What is the difference between acceptance criteria and a definition of done?

A definition of done is the general, reusable standard of completeness for any work item. Acceptance criteria are the specific, testable conditions for a particular deliverable or milestone. On a fixed-price build the acceptance criteria are what a client signs off against to release payment.

Why should sign-off record the commit hash and model version?

On builder-generated code a later re-run can rewrite accepted work, so acceptance must pin to a specific reviewed commit. Recording the model and version each AI feature was accepted on turns a later model deprecation into a clear warranty or change-order question rather than a dispute about whether the feature ever worked.

Does owning the source code guarantee a clean handover?

No. Owning the application code is not the same as owning a portable data layer. On a builder with a proprietary database the data-export test can be harder to pass than on a raw PostgreSQL stack, so if genuine portability matters, make the data-export format an explicit acceptance criterion rather than assuming code ownership covers it.