Why SDD fails without harness engineering

Cover

Why SDD fails without harness engineering

You adopted spec-driven development. You write specs now, you’re careful, you also review them. You generate code from specs. You stopped doing “only” vibe coding.

It works better than before. But it’s still not… right.

Then you realize: you’re doing SDD without harness engineering. Specs aren’t enough. You need enforcement.

Specs are not enough: why SDD fails without harness engineering

Vibe coding breaks because there’s no spec. The simple solution: add specs. Spec-driven development. Problem solved?

Not quite.

Here’s the tension: specs make AI generated code more reliable. But specs alone don’t ensure the code works. Specs can encode false assumptions. Specs can be incomplete. Specs can drift from implementation. And AI agents still hallucinate even when you give them a spec, they just hallucinate in different ways.

Enterprises discover this quickly. They adopt spec-driven development (SDD). They write specs, ideally careful. They use specs to generate code. They get… not terrible code, code that in most cases, ideally, touchs the (business) use caes. Better than vibe coding. But not reliable enough for production governance.

Then they blame the framework: “SDD doesn’t work.”

What actually happened: they did SDD without harness engineering.

The promise of spec-driven development

The pitch is clean. Spec-driven development moves from “vibe coding” to intent engineering.

You write down what you want: the architecture - the part, that we missed in the previous article. So, we have now the architecture, with the constraints, guard rails and the requirements. The spec is unambiguous, isn’t it?! You feed the spec to an AI agents. The agents generate code to match the spec. Done.

Better code → fewer surprises → less risk.

This is true. Spec-driven code is more reliable than vibe coded code.

But “more reliable than terrible” isn’t the same as “reliable.”

What breaks in SDD without harness

Three key failures emerge when you do SDD without harness.

First: specs encode assumptions. You specify: “Use JWT for authentication.” That’s a decision. It’s a decision on the one hand, but it’s also an assumption. Because, you assumed JWT is right for your context. You assumed the team implementing it understands JWT token refresh patterns. You assumed a key rotation strategy, you did not defined any JWT or OIDC library. The spec doesn’t say any of this details, it is just - vague.

The agent generates code that uses JWT. Technically correct to the spec. But, operationally wrong if your team doesn’t have a key rotation process, or uses a different library (e.g. Spring Security instead of a custom library). But this is/was not defind in the spec, so nothing that could flagged wrong or missing. With this, all good, it ships.

Assumptions encoded in specs look like they’ve been decided, explicitly. The worst thing is assumptions that haven’t been written down.

Second: specs can be incomplete. You specify what the code should do. You don’t specify what it shouldn’t do. The spec says: “Return order details.” It doesn’t say: “only return order details that belong to the authenticated user.”

The AI agent, following the spec, generates code that returns all order details to anyone who asks. Technically, this satisfies the spec. But from the security perspective - of course not, it fails.

This isn’t a SDD problem. It’s a human problem. But it’s a human problem that hits harder when you’re generating code at scale. You can’t review thousands of specs the way you review hundreds of designs. And let’s be honest, when was the last time you worked out a specification in such a detail that it covered every aspect: functional and non-functional requirements, use cases, component and deployment diagrams, decoupling / modularisation, data schema and much more.

Third: specs drift from implementation. You write a spec, initially this is the base and the code is generated from it. Some iterations later, someone adds a feature that the spec didn’t anticipate. They update the code but not the spec. To be honest (again), this issue is a challenge event without AI, so it’s nothing new.

However, the whole thing is being stepped up, when the next time, the AI agent uses the newly updated spec to enhance the code. But in this case, is the AI agent working with a changed spec and outdated code, or vice versa.

We know that, it is nothing new: Specs without enforcement become stale.

Why agents hallucinate even with specs

Here’s something that surprises enterprises: AI agents still hallucinate with specs. Different kind of hallucination, but still hallucination.

Imagine the following, we have defined a spec, and the AI agent use it as the base. The code base has a pattern for error handling that contradicts the spec (because it is not clearly defined, see the prev. sections). Now, usually the AI agent will use the pattern they see in the code base, this is his (reasonable) guess and assumption. It is an assumption for the AI agent, for the human is it a hallucination. Why? it is not clearly defined in the spec.

The clarity here is: Specs reduce hallucination, but don’t eliminate them entirely.

The missing piece: harness engineering

So if specs aren’t enough, what is?

Harness engineering (at the time of writing).

Harness engineering is the runtime environment where AI agents operate. It’s the “frame and constraints of the game” for code generation.

Think of it in layers:

Inner harness: The agent’s working environment. This includes:

  • Specs (what to build)
  • Architecture rules (how to build it)
  • Quality checks (did it work?)
  • Testing requirements (does it pass?)

Outer harness: The deployment environment. This includes:

  • CI/CD gates that enforce policy
  • Security scanning that prevents deployment of risky code
  • Observability rules that flag unusual patterns
  • Compliance checks that verify governance

The inner harness tells the agent: “Here are your frame and constraints. Work within them.” The agent generates code that matches the spec AND follows the architecture rules AND passes the quality gates.

The outer harness tells the deployment system: “This code has to pass these gates before it ships.” If the code doesn’t meet the harness requirements, it doesn’t deploy.

This interplay enable us - once again(!) - to embed the various disciplines of specification, high- and low-level design, test coverage and quality gates into this “agentic-based SDLC” construct, where all phases and activities are integrated, in line with the interaction between LLMs and AI agents.

Why harness makes SDD work

With harness:

Assumptions get surfaced. The architecture rules say: “All JWT implementations must use the key rotation service and use the interfaces from libray X.Y.Z” Now when the AI agent generates JWT code, if it doesn’t call the key rotation service, it fails the quality gate. The assumption is not an assumption anymore, because it is transfered to a requirement.

Gaps get caught. You write a spec that says “return order details.” The harness includes a security gate that says: “All data returns must include access control checks, and belong to the requested user.” The code generated by the AI agent now fails at this stage, unless it includes the check. The impact of requirements is being assessed across various areas (code base, testing, NFRs etc).

Drift gets detected. The harness includes tests that enforce the spec. If the code drifts from the spec, the tests fail. With that and the defined quality gates, the deployment will be prevented. Specs stay relevant because they’re continuously verified and adjusted.

Hallucinations get constrained. The architecture rules are explicit. The agent can hallucinate, but only within the boundaries. A hallucination that violates the rules fails the gate. An AI agent can’t accidentally invent a new error-handling pattern if the harness requires using the enterprise pattern.

With Harness engineering makes specs actually matter, in the entire SDLC process, from analysis and specification, coding, testing until deployment.

The resolution: SDD + Harness

Spec-driven development without harness is faster than vibe coding but not reliable enough for enterprises.

Spec-driven development with harness is both fast and reliable. You get the velocity of spec-based generation plus the governance of enforced rules.

Let’s reflect:

  • Is this more work than vibe coding? Yes.
  • Is it more work than SDD alone? Also yes.
  • Is it faster than traditional development with humans building code to design documents? Yes, dramatically.
  • Is it reliable enough for production governance? Yes.

This is the foundation. Governance speed gap, black box development, work product loss, all of these become solvable once you have SDD + harness.

That’s enterprise-grade AI development - in theory.


Key tensions this raises

  • Spec authoring overhead: Does writing specs take more time than you save?
  • Harness enforcement: Can you make the harness strict enough to prevent problems without making it so strict that nothing ships?
  • Agent autonomy: If the harness is too restrictive, AI agents become code generators instead of creative problem-solvers.

What’s next

The next article shows why even SDD + harness requires governance speed. The harness can be restrictive. Governance can slow you down. How do you govern “fast”?


References


Disclaimer

This article is part of a series exploring challenges and approaches in AI for SDLC and PDLC, covering architecture, methods, and sovereignty.

The AI space moves fast. What works today may feel outdated tomorrow and wrong the day after. Review these ideas critically and decide what applies to your context.

These views reflect the state of knowledge at the time of writing. No guarantee of correctness, especially as the field evolves.

Last Updated: 2026-05-17


See also