Cohesive Systems logoCOHESIVE SYSTEMS

Commoditizing Determinism

AI is making code cheaper.

That does not make software systems cheaper in the same proportion. It changes where the constraint lives. When syntax, scaffolding, glue code, tests, migrations, adapters, and local refactors become easier to produce, the expensive question moves upstream: what does the system mean, what must remain true, and where can change happen without breaking that meaning?

The scarce resource is no longer the ability to emit plausible code. It is deterministic system understanding.

Code Is Becoming Cheap

For decades, software teams treated code production as a central bottleneck. There were good reasons. Boilerplate took time. Framework conventions had to be remembered. Integrations required repetitive ceremony. Tests, migrations, serializers, schemas, client bindings, validation paths, and API handlers all had to be written by someone who could hold both the syntax and the intent.

AI changes the marginal cost of producing syntax. A competent model can draft a component, convert a data shape, write a repository method, generate a migration, translate an interface between languages, explain a compiler error, or produce the first version of a test suite. None of this makes engineering automatic, but it does make code less rare.

That change is easy to misread. If code is cheaper, the tempting conclusion is that teams should produce more of it: more variants, more services, more features, more rewrites, more generated abstractions. Some of that will happen. But abundant code also increases the surface area that must be understood, verified, governed, and evolved.

The gain is real. The bottleneck moves.

Comprehension Becomes the Bottleneck

The hard part of a mature system is rarely "can someone write code that compiles?" It is whether the change preserves the right meaning.

Teams need to know:

  • Which facts are authoritative, derived, cached, or merely observed?
  • Which invariants must hold before and after a change?
  • Which boundaries separate ownership, trust, failure, latency, and commit?
  • Which effects are allowed, required, delayed, compensated, or forbidden?
  • Which users, roles, regions, tenants, contracts, and runtime states change the answer?

These questions do not live in one file. They are distributed across domain language, product commitments, infrastructure behavior, runtime traces, business exceptions, incident history, tests, design decisions, and code.

When code was expensive, teams could sometimes rely on the friction of writing it. A large change forced a long conversation. A migration forced review. A new service forced architecture debate. AI reduces that friction. A large change can arrive as a tidy diff before the team has agreed what the diff is allowed to mean.

That makes comprehension the governing bottleneck. The central question becomes whether the organization has an authoritative account of the system strong enough to evaluate cheap change.

LLM Comprehension Is Useful but Not Authoritative

LLM comprehension is useful. A model can read code, docs, tickets, pull requests, logs, traces, Slack threads, support cases, design artifacts, and schema definitions. It can summarize a subsystem, identify likely ownership, infer missing context, explain how a feature works, and draft a plan.

That is valuable. It is not the same as a durable semantic source of truth.

The model is performing inference over context. Some of that context is stale. Some is contradictory. Some was aspirational when written. Some describes a temporary exception that became permanent. Some records what happened, not what should happen. Some is visible to the model; some is outside the window; some is inside a person's memory.

A model can produce a plausible map of the system, but plausibility is not authority. It can say, "this appears to be an idempotent workflow," but that is different from a reviewed system statement: "this operation is idempotent under these keys, across these retries, with these failure modes."

The difference matters because software systems do not only need explanation. They need commitments. They need facts that can be reviewed, versioned, tested, queried, and used to reject invalid change.

Abstraction as Precision

Dijkstra's view of abstraction is useful here. Abstraction is not a way to be less precise. It is a way to create a semantic level where precision becomes possible.

At the wrong level, every detail competes with every other detail. The code has HTTP handlers, database rows, retries, queue names, CSS states, serializer options, deployment flags, feature toggles, and access-control checks. These are real details, but they are not all the same kind of fact.

At a better level, the system can say: this is an entity, this is a transition, this is a projection, this is a policy, this is an observer, this is a boundary, this behavior is a requirement, this backend capability is a realization constraint.

That kind of abstraction is not a decorative architecture diagram. It is a precision instrument. It gives the system a vocabulary for stating what must remain true independently of one current implementation.

Code then becomes one realization of that meaning: necessary, concrete, executable, and inspectable, but not the only place where the meaning should exist.

The Wrong Kind of Modularity

Cheap code also exposes a common weakness in modular design.

Many systems are modular at the syntactic level. They have packages, services, repositories, bounded folders, API clients, generated types, shared libraries, and deployment units. Those modules may be useful. They may improve build times, ownership, and local reasoning. But they do not automatically align with system meaning.

A service boundary can cut through a business invariant. A shared package can hide a policy that should be owned by a domain. A generated client can make a remote dependency look local. A folder can group files by framework convention while scattering the actual behavior across handlers, jobs, schema migrations, feature flags, and dashboards.

The more durable target is domain-aligned semantic modularity. A semantic module has a reason to exist beyond file organization. It owns a portion of meaning: entities, transitions, policies, relations, projections, effects, observations, or commitments that change together.

This is a deeper modularity argument than this article needs to carry. The surface point is enough: AI can manufacture syntactic modules faster than teams can understand them. The valuable module is the one whose boundary lines up with meaning, not merely with code shape.

The System Is Scattered Across Tools

Code is only one projection of the system.

Linear records accepted work, rejected work, priorities, exceptions, and unresolved product tension. Figma records flow, hierarchy, interaction states, and user-facing commitments. Notion records decisions, strategy, glossaries, and operating assumptions. GitHub records review, intent, tradeoffs, and actual change. Slack records the conversation that explains why a thing was done. Observability records runtime behavior. Support records what users experience. Product discussions record what the system is supposed to become.

None of these tools is the system by itself. Together, they contain much of the meaning needed to change the system safely.

The problem is that the meaning does not accumulate deterministically. It accumulates socially. People remember. Teams agree informally. A staff engineer knows why a service behaves oddly. A designer knows why a flow has an exception. A support lead knows which "edge case" is actually a core customer workflow. A model can search across the trail, but the trail is still a trail.

If code generation becomes cheaper, this scattered meaning becomes more expensive. Every generated change has to be reconciled with facts that are outside the codebase or only weakly represented inside it.

Toward Deterministic Accumulation

The answer is not to stop using LLMs for comprehension. The answer is to turn useful comprehension into accepted system knowledge.

Deterministic accumulation means that when a team learns something about the system, the accepted version becomes part of a durable representation. Not just a paragraph in a doc. Not just a comment in a pull request. Not just a memory in a thread. A fact with a shape, owner, provenance, and relationship to other facts.

For example:

  • This operation is safe to retry because this transition is idempotent under this identity key.
  • This page is a projection of these authoritative facts, with this permitted staleness.
  • This policy applies before this effect crosses this boundary.
  • This external integration is eventually consistent and can produce duplicates.
  • This state is reconstituted from this durable history, not from the current cache.

LLMs can help draft these statements. Tools can discover evidence for them. Humans can review them. Tests and runtime checks can challenge them. But once accepted, the statements should become part of the system's durable semantic surface.

Deterministic does not mean the organization never has uncertainty. It means the accepted state is explicit. It can be diffed. It can be queried. It can drive generation. It can warn when new code contradicts an accepted invariant. It can tell an agent which facts are authoritative and which are only inferred.

The Thesis

The next software layer should make system meaning:

  • explicit
  • reviewable
  • diffable
  • queryable
  • generative
  • agent-readable

That layer should not replace code. It should make code less isolated. Code should increasingly be generated from, constrained by, checked against, and explained through a durable account of system meaning.

The shift is simple:

cheap codescarce trusted understanding\text{cheap code} \Rightarrow \text{scarce trusted understanding}

When the cost of producing syntax falls, the value of deterministic comprehension rises. The durable artifact is not only the repository. It is the accepted model of what the repository, runtime, product, and organization mean together.

Cohesive is one attempt to build around this premise: that the system graph should become a first-class artifact, and that code should increasingly be generated from, constrained by, or explained through that graph.