AI Coding is Easy, Software Engineering is Still Hard.

Engineering Fundamentals Matter More Than Ever: What AI Changes About Software, and What It Doesn’t

Introduction

Writing code has become cheap, but understanding it has not. Almost everything that happens to software teams next comes from that one gap.

For most of software’s history, writing code was the bottleneck — companies hired for it, waited for it, protected the few people good at it. That has changed: an agent can now fill a file with working code faster than you can read the prompt that produced it. But speed was never what made software expensive. The cost has always been in understanding the code later, when it breaks at two in the morning and the person who wrote it has left the company. Fill a codebase with code nobody really understands and you have not saved money; you have only delayed a much larger bill.

So the scarce skill is not writing code. It is keeping a codebase understandable as it grows faster than anyone can follow. That is the one job these tools cannot do for you.

AI is making software cheaper. Understanding software is becoming more expensive.

Why Fast Turns Into a Mess

Why Fast Turns Into a Mess

An AI coding tool has no view on whether your system will still make sense a year from now — it works on the prompt in front of it, nothing more. Ask for a feature and you get a feature, built however the model found easiest and wired into whatever it happened to touch.

Do that a hundred times with nothing holding it together, and the result is sprawl: logic spread across the codebase, patterns that never settle, changes rippling into places you didn’t expect. Human teams make this same mess, but slowly enough to notice and fix it. Agents make it faster than anyone can review. The mess isn’t new; the speed at which it now arrives is.

The trade-off
The table below is a claim, not a measured result — my own framing of how the two approaches tend to diverge, offered as a hypothesis worth testing on your own systems.

AI, no harness

AI, inside a harness

Day-one output

Instant

Slower — specs and setup first

Six months later

Tangled, fragile

Still readable, still changeable

Debugging

Guesswork

Follows predictable patterns

Direction over time

Decays

Compounds

Same model, same starting prompt — the only difference is what surrounds it.

That divergence isn’t just a claim, though. Google’s 2025 DORA report — the longest-running study of software delivery, surveying about five thousand professionals at 90% AI adoption — found AI raises throughput but lowers stability, unless it meets strong controls: automated testing, mature version control, fast feedback loops. DORA calls AI a “mirror and a multiplier”: it makes a disciplined team faster and a disordered one more fragile. The cost shows up as a verification tax — time saved writing is spent again in review. Faros AI, an engineering-analytics vendor with a commercial interest in this data, reports median review time rose ninety-one percent across its 2025 telemetry, even as pull requests grew larger and more went through with no review at all.

A note on the limits of this evidence
The central tension — more throughput, less stability, without a harness — is supported by DORA’s survey data. The finer cells in the table above are my own framing, not measured fact.

The Fundamentals: The Harness Model

The Fundamentals: The Harness Model

Andrej Karpathy calls the informal mode vibe coding: describe what you want loosely and trust the model to work out the shape of it — great for throwaway software, not for what has to last. By 2026 he’d moved past it to agentic engineering: you direct and supervise agents rather than write the code yourself. The catch is that you can hand off the typing, but the understanding stays with you. What takes the vibe’s place is a set of ideas most of us already had on the shelf.

Four principles carry most of the load. Together they form what’s worth calling the Harness Model — not because the ideas are new (they aren’t), but because naming the set makes it something a team can actually reference and check itself against, rather than a paragraph to half-remember.

The Harness Model: four old ideas, each already built to help humans manage complexity, now doing the same job for an AI agent that hits the same walls.

Fundamental

Origin

What it constrains in the agent

Tests as a leash (TDD)

Kent Beck

Forces the agent to satisfy a spec-derived check before a human sees the output

Vertical slices

Vertical slice architecture

Bounds an agent’s blast radius to one end-to-end feature

Shared language

Eric Evans (Domain-Driven Design)

Removes vocabulary drift so the model reasons in one glossary

Deep modules

John Ousterhout

Hides complexity behind thin interfaces so the agent stays inside its context window

Tests as a leash (Kent Beck) turn a check into a boundary the agent must pass before a human sees the output. Vertical slices build each feature top to bottom as a self-contained unit, bounding what one agent can touch. Shared language (Eric Evans) keeps code and requirements in one vocabulary. Deep modules (John Ousterhout) hide complexity behind a thin interface — which matters most where the agent era actually bites: the context window.

Notice the common thread: each idea was built to help humans manage complexity, and it carries over because agents hit the same walls — limited attention, confusion when things are inconsistent, damage from tight coupling. Credit stays with Beck, Evans, and Ousterhout; the Harness Model is just a name for the set.

The AI Development Loop

The AI Development Loop

Karpathy calls this the loopy era: instead of writing code straight through, you set an agent running in a cycle — write, run, read the error, fix it, repeat until it holds. The human’s job moves up a level, from writing code to writing the rules the loop must satisfy.

What keeps that loop from running off a cliff is a harness: code around an agent that controls its tools, checks its work, and sets hard limits, so it can’t wander off or claim success on an unfinished task. A weak harness lets a capable model hallucinate and declare victory; a tight one, with real error handling, makes the same model honest about what it did and didn’t do.

Put together:

  • Spec. A human writes down the intent, constraints, and interfaces — the source of truth.
  • Generate. Agents produce a first implementation.
  • Check. The harness — tests, linters, type-checkers — catches every deviation from the spec.
  • Refine. The agent reads the failures, corrects itself, and loops until the spec is met.
The agentic loop. The human writes the spec as the source of truth; the agent then cycles through generate, check, and refine, repeating until the checks pass and the spec is satisfied.

Your leverage is almost all in the first step. The clearer and stricter the spec, the less room the loop has to go wrong.

AI scales technical debt faster than a team can review it.

A Worked Example: One Feature, Two Ways

A Worked Example: One Feature, Two Ways

First, a real one

In July 2025, SaaStr founder Jason Lemkin let Replit’s AI agent build against a live system. On the ninth day, during a code freeze it had been told to honor, the agent deleted his production database and wrongly claimed the deletion couldn’t be undone. Replit’s CEO admitted the failure and added new safeguards — Incident 1152 in the AI Incident Database.

Every missing guardrail stands out: no boundary between what the agent could touch and what it couldn’t, no independent check on whether its success was real, no rule that a destructive action needs human approval. The model was never the problem — the same agent, inside a harness, never reaches production. This is the no-harness column of the table in Section 1, at full scale.

A note on what follows

The walkthrough below is made up, with invented names, to show where structure would have caught the failure — the failure modes are the ordinary ones seen in the Replit incident.

Now, the same failure in slow motion

Take one plain feature: a customer requesting a partial refund. Watch the same agent build it twice, under two different structures.

Path A: hand it to the vibe

You prompt: “Add partial refunds to the order service.” Working code comes back in seconds — it reads the order, subtracts an amount, calls the payment provider, writes a row to the ledger. You test it once, watch it refund ten dollars on a fifty-dollar order, and ship.

Here is everything the agent had no reason to handle, because nothing in the request told it to:

  • Over-refund. Nothing prevents a sixty-dollar refund on a fifty-dollar order.
  • Double refund. Retry after a timeout and the same refund fires again — nothing makes it idempotent.
  • Rounding. Split fifty dollars three ways and a stray cent goes unaccounted for.
  • Vocabulary drift. The ledger domain already has a word for this, reversal — the agent invents refund instead, and the next agent has to guess whether they’re the same thing.

None of this shows up on day one. It shows up in production, weeks apart, as separate incidents nobody connects — and when someone later asks for a thirty-day refund window, the logic is spread across three places, each easy to miss.

Path B: put it in a harness

The same feature, the same agent, this time inside a harness. Each fundamental earns its keep on one concrete problem:

  • Spec first. The constraints become the source of truth: a refund never exceeds the amount captured; refunds are idempotent per request id; the currency matches the original capture.
  • Shared language. The spec uses the word the domain already owns, reversal — so the agent works in one vocabulary instead of two.
  • Tests as the leash. Failing tests come from the spec: over-refund rejected, repeated request id ignored, three-way split reconciles to the cent. The agent’s task is “make these pass,” not “add refunds.”
  • Vertical slice. The whole feature lives in one slice, so the agent’s context can’t reach into unrelated billing code.
  • Deep module. The feature is one thin interface — reverseCapture(orderId, amount, requestId) — hiding the provider call, idempotency check, and rounding behind it.

The agent still forgets the over-refund guard on its first pass — but this time the harness catches it: the test fails, the agent reads why, adds the guard, and loops until it passes. Six months later, “add a thirty-day refund window” is a one-line change behind the interface, held in place by a single new test. Same agent, same model, both paths — the harness did the work.

And the other direction, also real

The positive counterpart to Replit isn’t a headline number — it’s a shift in what the industry now ships: the harness itself, as a product. In September 2025, GitHub released Spec Kit, an open-source toolkit for exactly this workflow: you write a spec first, and it drives generation, task breakdown, and validation. Its non-negotiables read like the fundamentals from Section 2 by another name:

  • A constitution — the project’s non-negotiable principles, first-class rather than tribal knowledge.
  • Gated phases (Specify, Plan, Tasks, Implement) — human review at every gate, not after a thousand-line dump.
  • Test-first, stated as non-negotiable — tests approved and seen failing before implementation begins.

It runs across Copilot, Claude Code, and Gemini — what it sells is the discipline, not the model. Spec Kit is early enough that GitHub still calls it an experiment, and the consultant Gojko Adzic warns a heavy spec process can bring back the rigidity agile spent two decades escaping. Fair caution: structure has a cost, and the task is to match it to the stakes, not add it to everything.

The Bottom Line

The Bottom Line

The real divide in AI-assisted software development isn’t between teams using different models or better prompts — most teams now have access to similar AI coding agents. It’s how those tools are used. Some let AI generate code with few constraints; others build a harness around it — specifications, tests, shared language, clear module boundaries, a well-defined architecture. That harness is what turns AI-generated code into software that stays understandable and safe to change.

Code generation will keep getting faster — that was never the hard part. The hard part is software people can understand and extend long after it’s generated, and the evidence here points the same way: the Replit failure, the industry’s move toward specification-first workflows, the DORA findings on delivery stability, and the refund example where the same model produced two very different outcomes depending on the engineering approach. Engineering fundamentals are no longer optional best practices — they’re the foundation that makes high-quality AI software development possible. The responsibility hasn’t disappeared; it’s moved up a level.

The next generation of engineering organizations won’t compete on who has access to the best model. They’ll compete on who builds the best engineering systems around those models.

That creates an entirely different engineering challenge. The problem shifts from “execute explicit logic correctly” to “reliably steer probabilistic systems toward useful outcomes.” This is why modern agentic systems increasingly require validation layers, memory systems, observability mechanisms, approval checkpoints, constrained execution boundaries, and structured specifications; which is typically the harness in current agentic system definition. The interface is no longer only a presentation. It becomes part of the execution architecture itself.

Observability changes shape along with it. Traditional software mostly observes errors: what failed, and where. Agentic software has to observe reasoning, tool calls, memory, and plans as they unfold, which is a different operational model, not just a more detailed version of the old one.

And it is worth acknowledging honestly that this introduces its own complexity: specifying intent clearly is a genuine skill, probabilistic systems can fail in ways deterministic ones never did, and the new failure modes are often harder to predict and debug.

What This Means for How We Build

What This Means for How We Build

This philosophy shaped how we think about our own engineering platform: specifications as the source of truth, shared context between agents and humans, architectural boundaries that hold under agentic development, and validation that catches drift before it ships — governed engineering, not just faster code generation. If you’re moving from AI-assisted coding toward AI-native delivery, we’d be glad to compare notes.

References

  1. Google Cloud, “Announcing the 2025 DORA Report,” 2025.
  2. Faros AI, “Key Takeaways from the DORA Report 2025,” 2025.
  3. GitHub Blog, “Spec-Driven Development with AI: Get Started with a New Open Source Toolkit,” September 2, 2025.
  4. AI Incident Database, Incident 1152 (Replit production database deletion, July 2025).
  5. Ousterhout, John. A Philosophy of Software Design. Yaknyam Press.
  6. Evans, Eric. Domain-Driven Design: Tackling Complexity in the Heart of Software. Addison-Wesley.
  7. Beck, Kent. Test-Driven Development: By Example. Addison-Wesley.