The acceptance criteria were clean. Given/When/Then, every branch covered, nothing left ambiguous. The delivery side — engineer or agent — built exactly what they said. Every test went green. And the thing that shipped was still wrong — the kind of wrong that takes a week to explain and a sprint to undo.
Nobody on that chain made a mistake you could point to. The criteria were met. That is the unsettling part: the handoff did precisely what it promised, and the promise wasn't enough.
We keep calling that handoff the API between product and engineering — the clean interface, the structured list you write once and pass across. The framing is right. What's wrong is what we think the API is. The acceptance criteria aren't the API. They're the signature of the API. And a signature with no semantics behind it isn't a contract — it's a shape. Hand a capable builder a shape and they will fill it competently, confidently, with the wrong thing.
The crossing point is a contract, not a territory
Start with what the metaphor gets right, because it settles an argument that has been eating a lot of oxygen.
Engineering's side of the loop is being rebuilt right now. Ryan Lopopolo of OpenAI calls the emerging discipline "harness engineering" — making the standard for good code legible to an agent and surfacing it just in time, so that the agent, not a person, produces most of the diffs. It is a serious body of practice, and it is moving fast. The natural reaction from the product side is territorial: if engineering is building an agent harness, and I have something called ProductHarness, who owns the thing?
Wrong question. The crossing point between discovery and delivery is an interface, and an interface is owned by neither side. Product owns the contract. Engineering owns whatever sits behind it — a headless agent harness, a team pulling tickets from a board, anything in between. That is the org's call, and it should vary by project, by risk, by how mature the delivery pipeline is. If the contract handed across the seam is real, you should not care where delivery does its work. This is the oldest idea in software design wearing new clothes: define the contract, leave the implementation free.
So the positioning question answers itself. You are not fighting engineering for the harness. You are supplying the one artifact their harness consumes. That is a stronger place to stand than any turf claim, and a more honest one.
But it only holds if the contract is genuinely a contract. This is where the tidy story breaks.
A signature is not an API
Every engineer who has integrated against a badly documented endpoint knows the failure. The function name is right there. The parameters have types. You can call it. And you still build the integration wrong, because the name and the types told you the shape of the call and nothing about what it means — what the values are allowed to be, what happens at the edges, what the thing is actually for.
A bare list of acceptance criteria is that endpoint. It says what must be true for the work to be accepted. It says nothing about why those conditions were chosen, what was tried and rejected on the way to them, or what the feature is in service of. A builder working only from that list will satisfy every criterion and can still produce something that passes and misses — technically green, structurally wrong.
This was always a risk with human delivery, and senior engineers quietly absorbed it. They filled the gaps from hallway context, from having been in the room, from institutional memory about what the company actually cares about. The acceptance criteria were thin, and the org's accumulated judgment silently made them thick.
Agents do not have the room. They have no hallway, no standup, no scar tissue. An agent works from the specification in front of it, not from what everyone on the team already knows. Whatever is not in the contract is, for the agent, simply absent. The thin handoff that human teams survived becomes, with an agentic delivery side, a direct instruction to build to the letter and ignore the intent — because there is no intent on the page to honor.
The semantics live in discovery
Here is the part the headline hides. The thing that makes a contract thick is not more acceptance criteria. It is the discovery context that produced them.
The problem definition — who this is for and what's actually broken — tells the builder which interpretation of an ambiguous criterion is the right one. The validated prototype tells them what "working" looked like when a real person touched it, not what the prose approximated. The options explored and rejected tell them which clever alternative not to reach for, because it was already tried and it failed validation for a reason that isn't obvious from the outside. The evidence against the four product risks — value, usability, feasibility, viability — tells them what was actually proven versus what was assumed.
None of that is acceptance criteria. All of it is what lets the delivery side make a good decision at the dozen small forks the criteria never anticipated. Acceptance criteria get you conformance. The discovery record is what gets you a better solution instead of a compliant one. A spec tells you when to stop. The context tells you which way to go while you're still moving.
This reframes what the API even is. The acceptance criteria are the surface — the part you can test against, the part that says pass or fail. The real contract is that surface backed by its meaning. Strip the meaning and you have not handed over a smaller contract. You have handed over a more dangerous one, because it looks complete and isn't.
This is why the repo beats the ticket
Now the practical consequence, and it is the one that should change how a team works on Monday.
A backlog ticket is a thin API by construction. The acceptance criteria arrive in the description field, severed from the problem framing, the prototype, the rejected directions — those lived in documents, in conversations, in a Figma file, in someone's head, and the ticket carried none of them across. The delivery side receives a signature and is told to integrate. Every gap gets filled by guessing, and an agent guesses without even knowing it's guessing.
A repo carries the contract whole. The acceptance criteria sit next to the requirements that generated them, the prototype that validated them, and the decision record that explains them. The API is self-documenting because its documentation is its neighbor in version control. The delivery side — human or agent — can follow the criterion back to the reason for the criterion without leaving the environment it's working in.
This sharpens a claim I've made before about being indifferent to where engineering works. I am indifferent to the location of delivery. I am not indifferent to the fidelity of the context that travels with the contract. The seam can sit anywhere. What crosses it cannot be thin. A board is fine as a tracking mirror; it is a lossy place to author the contract, because it strips the contract down to its signature on the way in.
"Discoverable" was never enough. The word that mattered was always the second one: discoverable and consumable — and consumable now means thick enough that the other side can reconstruct the intent, not just check the boxes.
What to do now
If you take one thing from this, make it a habit, not a belief.
Author the contract where its context lives. Write acceptance criteria in the repo, next to the problem statement, the validated prototype, and the decision log that produced them. Not because the repo is fashionable — because it is the only place the API carries its own semantics across the seam.
Make the rejected paths discoverable, not just the chosen one. The most valuable thing in a discovery record is often what was tried and abandoned. Leave it in. It is the guardrail that stops a builder from confidently rediscovering a dead end.
Treat "consumable by an agent" as a design requirement, not an afterthought. If your delivery side is becoming agentic — and Lopopolo's harness is one sign of how fast that is happening — then the contract has to be legible to something with no institutional memory. Assume the reader knows nothing the page doesn't say. Write accordingly.
Check the contract is thick before you cross. The gate between discovery and delivery is not "are the acceptance criteria written." It is "could someone who wasn't in the room build the right thing from what's on the page." If the answer is no, you have a signature, not an API, and you are about to ship the gap.
The acceptance criteria are the API. Just remember what an API actually is. The signature is what you can test. The semantics are what makes it worth calling. Hand over both, or you haven't defined an interface — you've only described its shape, and shapes get filled with whatever's nearest.
Source. This piece was triggered by Ryan Lopopolo (OpenAI), "Harness Engineering: How to Build Software When Humans Steer and Agents Execute," a talk delivered at AI Native DevCon and published on the AI Native Dev YouTube channel, June 19, 2026: youtube.com/watch?v=c8bE0cj7vHY. Lopopolo's talk concerns the engineering side of the loop; the argument here about the discovery-to-delivery contract is my own extension, and all characterizations of his remarks are drawn from that talk. I have no relationship with OpenAI, AI Native Dev, or the conference.