Skip to main content

Vibe Coding Increases Entropy. Harness Engineering Reduces It.

Let us begin with a synthetic case. It draws on patterns common in AI coding projects to illustrate the mechanism; it does not describe a specific client.

A factory wants to build a production scheduling system. In the first week, the project lead explains the orders, inventory, machines, and delivery dates to an agent. After a few rounds of conversation, the login page, order list, inventory dashboard, and scheduling Gantt chart are all running. Features that would once have waited in a two-month development plan are clickable within days.

The team is thrilled. They add rush orders, material shortage alerts, operation reporting, role-based permissions, and mobile pages. The agent delivers new changes every day. A month later, the system has dozens of screens, and functionality has grown far beyond the original expectation.

By the third month, a different pattern emerges. The order ID field has three names across three modules. Two pages each implement their own date picker. Scheduling gains a new “pending confirmation” state, while an old report still recognizes only the previous four. Every test passes, yet the drag control on the Gantt chart occasionally stops responding. The documentation is thorough, but it describes the product as it existed six weeks ago.

Each change makes sense in isolation. Once the changes accumulate, understanding the system takes longer and longer. The code keeps racing ahead while the team’s understanding falls behind.


Code Moves Faster Than Understanding

Vibe coding dramatically lowers the cost of producing candidate solutions. A person states the requirement, and a model can change the frontend, backend, tests, and documentation together. For the first time, a project can have an almost excessive capacity to implement.

Human attention does not scale at the same rate. The product lead still has to judge whether scheduling rules match the factory floor. Engineers still have to check for permission flaws. Tests still need to cover real environments. Documentation still needs to catch up with every change. Once code generation stops being scarce, verification, selection, and maintenance become the bottleneck.

The scheduling system’s diverging fields, duplicate components, missing state handling, and stale documentation can all be understood through one term: software entropy. Here, entropy is an engineering metaphor for the duplication, drift, inconsistency, and maintenance burden that accumulate inside a codebase. Thermodynamic entropy and information entropy have their own precise meanings; this article borrows only the intuition that order requires continuous upkeep.

A simple relationship helps us reason about the speed of drift:

Net drift ≈ accepted change rate × escape probability − cleanup rate

Suppose a team accepts ten changes per day and one undetected problem slips through. If an agent raises the rate to one hundred changes while inspection capacity stays flat, unresolved problems accumulate much faster. If test coverage, type checks, and runtime verification expand at the same time, the escape probability falls. Agents can also accelerate cleanup. The outcome depends on the relative speed of all three forces.

Vibe coding therefore amplifies both output and the project’s existing capacity for governance. When verification keeps pace, speed can fund repairs and refactoring. When it does not, locally reasonable changes gradually combine into global drift.

The scheduling team’s new problem is clear: generation has scaled, so the project needs a selection system that can scale with it.


How Drift Accumulates

Software drift rarely begins with one dramatic failure. It usually starts with a small convenience.

Writing a new conversion function for a page is faster than finding the old one. Adding one branch for a new state is faster than auditing every consumer. Updating a document from the current context is faster than reconstructing six earlier decisions. Each choice optimizes the task in front of the agent while increasing the number of possibilities that someone must distinguish later.

Models also learn the patterns already present in a codebase. Once the repository contains its first temporary workaround, later generations are likely to extend it. Good patterns replicate, and bad patterns spread too. OpenAI observed a similar effect in its fully agent-generated codebase and introduced recurring cleanup tasks in response.

This accumulation explains why a single code review cannot resolve long-term drift. Review focuses on the current change; software entropy emerges from relationships among changes. Did the new state reach every report? Does the new permission check cover every entry point? Does today’s documentation still match the running system? As the project grows, no one person can hold every relationship in mind at once.

The team needs to observe the state of both code and product continuously, retain qualified results from a stream of candidate changes, and carry each lesson into the next generation. That resembles a classic thought experiment.


Maxwell’s Demon and the Cost of Order

In 1867, James Clerk Maxwell imagined a box divided into two chambers by a partition with a tiny door. A demon watches gas molecules approach the door, sending fast molecules to one side and slow ones to the other. Through continuous sorting, a temperature difference appears and the box seems to become more ordered.

Szilard later brought information into the problem. In 1961, Landauer argued that logically irreversible information erasure has a minimum thermodynamic cost. Bennett then clarified the role of resetting memory within the full cycle. A 2012 experiment focused on verifying this cost in the erasure of a one-bit memory.

This history of physics serves as an engineering metaphor here. Its equations cannot calculate the price of a CI run, a model call, or an hour of human review. The useful lesson is simpler: continuous selection requires observation, judgment, action, and memory maintenance, and every one of those activities consumes real resources.

Back in the scheduling system, changes proposed by the agent resemble molecules arriving at the door. Type checks, tests, browsers, and logs observe them. Merge gates control the door. Specifications, error records, and architecture decisions provide memory. Stale tests and distorted documentation must be cleaned up periodically.

A prompt that says “keep the code clean” can influence the first generation. A browser check that reproduces the broken button can show the agent that the result has departed from the goal. Guidance lowers the chance of hitting a wall; feedback helps the system return after it does. Connecting the two creates a selection process that can keep running.

The scheduling team’s next move is to connect these activities into a durable engineering system.


A Harness Grows Around the Project

The team begins by writing down three business invariants: order quantities cannot be negative, a completed operation cannot return to the not-started state, and an ordinary operator cannot view cost data from another workshop. These invariants give every generation a shared target.

Next, the team organizes a field dictionary, a state-transition diagram, a page inventory, and a record of key decisions. When an agent starts a task, it can find the standard name for the order ID and understand why “pending confirmation” exists. Project knowledge moves from chat history into the repository, so the next generation no longer depends entirely on one person’s memory.

The third step makes the environment carry some of the constraints. Money and quantities receive explicit types and schemas. State changes can happen only through a state-machine interface. Ordinary agents receive limited database capabilities. New pages begin from a shared template. Many risks lose room to move before the code reaches a test.

Then the team adds sensors. Type checking and lint run after every edit. Unit tests cover scheduling calculations. Browser scripts open pages, click controls, and inspect the console. Logs and metrics expose startup health, API failures, and latency on critical paths. Failure information returns to the agent’s context and drives the next revision.

The team also defines the conditions for moving forward. A compilation failure, permission-test failure, or unusable critical page keeps a change outside the gate. After a failure is fixed, a new test, rule, or explanation is written back to the repository so future tasks inherit the lesson.

Once these capabilities are connected, the team has a Harness. A Harness is the engineering environment built around an agent. It connects goals, context, structure, verification, gates, repair, and the return of experience.

Green tests still have limits. One redesign of the Gantt chart passes every automated check, yet the factory owner finds machine conflicts difficult to see. Tests establish properties that have been expressed and covered. The owner’s experience is a separate validation channel. A complete Harness routes machine checks and human judgment to the places where each signal belongs.

Harness quality is determined by the whole chain. A wrong goal makes checks defend the wrong direction. Incomplete coverage produces false greens. Vague errors increase repair time. Bypassable gates weaken constraints. Stale project knowledge points the agent toward an obsolete world. Continuous governance lives at every connection.


Three constraint mechanisms, three kinds of cost

The scheduling system has a rule: order quantities cannot be negative. The team can give this rule to the agent through three mechanisms.

The first is Soft constraints. The team writes the rule in AGENTS.md, a field dictionary, or a Skill so the agent is reminded to validate order quantities before generating code. This changes the probability distribution of generation and makes a correct first attempt more likely. Soft constraints are cheap and portable, which makes them well suited to naming, style, exploratory rules, and human taste. As rules multiply and context grows, attention becomes diluted, so soft constraints cannot provide a guarantee on their own.

The second is Hard measurements. The team runs unit tests and data validation; a negative number produces an error, and CI prevents the change from advancing. Tests, compilation, lint, browser verification, and logs all belong to this layer. They observe actual results and give the agent reproducible feedback. Hard measurements require continuous investment: checks must be written, run, and maintained, and their effectiveness depends on coverage, error quality, and the completeness of the gate.

The third is Structural constraints. The team defines order quantity as a non-negative type, limits its range in the schema, and allows business code to change it only through a restricted interface. The agent’s available choice space becomes smaller. Types, schemas, templates, state machines, scaffolding, and restricted APIs can all play this role. Structure is useful for stable, high-cost invariants, and it carries construction, migration, and maintenance costs of its own.

The three mechanisms describe their primary effects and can overlap. Their timing helps explain them but does not form a rigid boundary. A type system combines the design of an expression space with compile-time checks. A template supplies a structural starting point that lint and tests can continue to protect.

The order-quantity rule deserves all three layers: a soft constraint communicates business intent, a structural constraint compresses the error space, and a hard measurement catches problems that still cross the boundary. The higher the risk and the more stable the rule, the more worthwhile layered protection becomes.

Frequent, decidable problems such as field naming are good candidates for early hard measurements. Directory and abstraction rules that are still evolving can begin as soft constraints and become structural once they mature. The visual hierarchy and interaction habits of a Gantt chart require prototype comparison and human judgment. After choosing the mechanism, the team must still decide how tight to make each layer.


Keep Freedom Inside the Boundaries

The team soon discovers that applying the same strictness everywhere creates a new problem.

Errors in permissions and financial data can spread into real operations, so those gates remain strict. The Gantt chart’s interaction model is still being explored, so the team lets the agent generate several alternatives quickly. Stable invariants form strong boundaries, while the space inside them remains free.

An overly tight Harness has recognizable signals: the agent retries the same check again and again, developers frequently bypass gates, local rules conflict, and simple changes wait through long feedback cycles. An overly loose Harness also has signals: duplicate implementations increase, fields keep diverging, documentation and the running system tell different stories, and production incidents slip through fully green tests.

Frequent, fine-grained checks shorten feedback. A field error appears during editing, a permission issue appears before commit, and a complete business flow is verified before release. The closer a problem is detected to where it was created, the less context is required to repair it.

Metrics also shape agent behavior. If the only goal is green tests, an agent may weaken the tests. If the only goal is fewer lines of code, essential validation may be compressed away. Teams need a combination of signals, controls over who may alter critical tests and rules, and spot checks of the actual product.

A Harness drifts over time too. Old rules obstruct new architecture, tests lose their power to discriminate, and documents preserve retired decisions. Periodically cleaning the Harness matters as much as cleaning the application code.

Governance itself adds code, tools, and rules. The team therefore begins asking whether each new piece of complexity is worth owning for the long term.


Complexity Needs a Budget Too

Generating a piece of code is cheap. Owning it over time still costs money and attention. Every custom component must be understood, tested, upgraded, and handed over. The scheduling team adds one step before writing code: first check whether the capability already exists.

The open-source Skill ponytail turns this idea into a decision ladder: ask whether the feature needs to exist, then search the codebase, standard library, platform-native capabilities, and installed dependencies before writing the smallest possible implementation. In a self-run evaluation of twelve bounded tasks in a FastAPI and React repository, the author reports an average reduction of roughly 54% in lines of code. The result illustrates a direction; generalizing it to other projects requires more evidence.

When a browser-native date picker is sufficient, the team avoids the cost of a component wrapper, custom styles, and future upgrades. Third-party dependencies bring supply-chain, versioning, and observability risks of their own. In OpenAI’s Harness Engineering case study, the team chose to implement a small concurrency utility for local behavior and observability.

A complexity budget considers the full bill: required behavior, risk, comprehensibility, dependency cost, and future change. Reusing a mature capability often reduces the surface area a team owns. In other cases, a narrow, explicit, verifiable local implementation costs less. The goal is always to keep added complexity proportional to added value.


Making Speed Sustainable

Return to the scheduling system in its third month. The agent has not slowed down. What changed is the environment around the project: business rules have a defined home, project knowledge can be retrieved, dangerous capabilities are restricted, pages can be exercised automatically, and failures leave experience that the next task can use.

The team gradually settles on six principles:

  1. Write down goals and business invariants first. Selection needs a stable direction.
  2. Scale verification and cleanup with generation. Net drift depends on the relative speed of the whole chain.
  3. Keep high-cost failures outside capability boundaries. Harden money, permissions, and data security first.
  4. Give decidable problems fast, specific feedback. Detect errors close to where they are created.
  5. Reserve human judgment for exploration and taste. Use prototypes and comparison to choose direction.
  6. Clean code, documentation, and the Harness periodically. The governance system also needs maintenance.

Vibe coding opens the faucet of code generation. A Harness adds pipes, filters, pressure gauges, and a return loop. The project can absorb more flow and send deviations back for repair before they spread.

In engineering terms, reducing entropy means a collection of everyday actions: observe deviation, block risk, repair the result, preserve the lesson, and remove stale rules. These actions turn the speed of code generation into a capability a team can sustain.


References