There are two sentences circulating through software engineering right now.
The first can sound like a boast:
I don’t read code anymore.
The second is a rebuttal:
I read the code.
There is an uninteresting version of this debate that we can put aside immediately. Some people will use AI as an excuse to abdicate responsibility. They will merge code they do not understand into systems where failures can harm people, expose data, or create consequences that are difficult to reverse. Nothing here defends that practice.
The interesting case is not the inexperienced developer who cannot inspect the work. It is the experienced developer who could read every line and deliberately chooses not to.
Why can experienced engineers reach opposite conclusions about something as basic as reading code? Because the argument quietly treats code inspection as a proxy for assurance, and determinism as a proxy for robustness.
That is the misunderstanding worth examining.
What deterministic machinery establishes
The familiar argument slides too quickly:
deterministic -> testable -> reliable -> robust -> trustworthy
Each step adds a property the previous one did not establish.
A compiler tells us that code can be translated under a language and target. A type system rules out declared classes of invalid programs. A passing test tells us that an assertion held for selected executions. Reading code can reveal behavior those checks miss.
None tells us that the requirement was right, the tests were complete, or the reader understood the domain.
Every guarantee contains an invisible prefix:
Given this specification...
Given these inputs...
Given this environment...
Given this definition of success...
Deterministic software can make an implication dependable. It cannot make its premises complete.
A million tests can preserve the wrong world
Imagine a product designed around the assumption that each device has one active user.
The team can test every permitted transition. Then the product reaches a field team where five people share one device.
The tests were not insufficiently deterministic. The model of the world omitted something important.
A test suite operates inside a selected universe:
inputs we imagined
conditions we modeled
assertions we wrote
failures we anticipated
This does not make testing weak. It makes testing scoped.
A test suite is evidence about behavior inside a model of the world. It is not evidence that the model contains everything that matters.
A specification is a map: useful because it discards most of the territory. Tests verify behavior on that map. They cannot recover what the map left out.
You cannot test for a category you have not yet learned to perceive.
LLMs made the old problem visible
Traditional software kept much of the ambiguity upstream:
Human interprets the domain
-> writes a specification
-> deterministic machine executes it
Agentic systems move interpretation inside the runtime:
Human states an incomplete goal
-> agent interprets it
-> agent selects evidence and tools
-> agent produces an artifact
The agent now helps construct the representation it executes. It may choose different sources, assumptions, and stopping points on each run. That creates real risk.
But forcing the same output would not make the framing correct. It might only reproduce the same mistake.
LLMs did not create the gap between specification and world. They made it computationally visible.
Robustness is a relationship
Robustness is not a material property. A system is robust against something, for some purpose, under some conditions.
Robust against malformed input
Robust against provider failure
Robust against prompt variation
Robust against concurrent updates
Robust against changing user behavior
Robust against malicious action
Each claim needs different evidence. Determinism helps with identity, repeatability, and legal transitions. Domain expertise, observation, and monitoring address different failures.
This is why veteran engineers can reasonably disagree about reading every line. For short-lived, reversible software, exhaustive review may cost more than the defects it catches. For authentication, infrastructure, or safety-critical systems, code inspection may be among the cheapest controls available.
Both positions can be right because the domain sets the assurance budget.
Three questions, not one
Three questions are routinely collapsed:
Implementation correctness
Did we build what the specification says?
Representational adequacy
Does the specification capture what matters in the world?
Decision adequacy
Is the result good enough to act on here?
Tests and formal methods are strongest at the first. Domain knowledge governs the second. Consequence and authority enter the third. The philosophy of computer simulations makes a similar distinction between verifying a computation and validating its model.
A verified model can still be a bad model. An accepted decision can still be false.
Assurance policy is normative
Assurance policy is not merely a technical estimate of correctness. It is a normative decision about which errors matter, who bears their consequences, and how much evidence is sufficient before acting.
Technical systems can estimate false positives and false negatives. They cannot decide which is worse. A fraud detector, medical screen, and creative assistant should not share an acceptance threshold because their errors have different consequences and reversibility.
The philosophy of risk calls this inductive risk: accepting or rejecting a claim always risks error. Wider epistemic risk enters through methods, assumptions, and interpretation.
So a “strict” policy is not simply more objective than a “fast” one. It may reduce one error while increasing another. It may add review without improving the model.
Assurance is not one slider from weak to strong. It is a configuration of risks, values, evidence, and authority.
An agent saying it is “80% confident” does not resolve this. The SEP’s discussion of certainty distinguishes conviction from epistemic standing. What matters is the basis: which sources support the claim, what conflicts, what was not inspected, and which assumptions remain.
Confidence compresses. Assurance exposes enough of the basis to make a decision inspectable.
Determinism is not one property
The philosophy of causal determinism distinguishes determinism from predictability. Software needs a similar decomposition:
Computational determinism
Same computation, same result.
Representational determinism
Equivalent content, one identity.
Control-flow determinism
State changes follow declared transitions.
Policy determinism
Rules select the required checks.
Commitment determinism
Approval binds to the reviewed object.
Replay determinism
History reconstructs the same accepted state.
Generative determinism
The same prompt produces the same output.
These properties are not interchangeable. The first six can often surround an agent even when the seventh is unavailable.
The question is not whether the whole workflow is deterministic. It is which properties must remain invariant and where variation is useful.
Deterministic boundaries, not deterministic thought
Exploration benefits from variation. Acceptance benefits from determinism.
Explore
search, interpret, hypothesize, revise
Accept
identify, check, approve, commit, record
Permit nondeterminism in how work is explored. Enforce determinism at the boundary where work is identified, checked, approved, and accepted.
The system should make narrower claims than “the answer is correct”:
This exact artifact was reviewed.
These checks ran against it.
These assumptions and uncertainties remain.
This authority accepted it for this purpose.
Assurance is not certainty manufactured by process. It combines evidence, methods, assumptions, review, authority, and traceability to make reliance sufficiently warranted for a particular decision.
A robust system is not one that has eliminated nondeterminism. It is one that knows what its deterministic machinery can prove, what its tests cannot see, and who must decide whether the remaining uncertainty is acceptable.