Results

What happened when we measured it

eleven recorded trials across four codebases. This page is organised by conclusion, not by chronology, and it includes the trial that refuted the hypothesis it was built to test.

A passing test suite is not evidence the work is done

This is the strongest conclusion on the site, it is supported from two independent directions, and it is the one with the clearest operational consequence.

0 of 5

Independent-verification findings the builder's own checks had already caught

Instrumented

Measures
Of five findings from a fresh agent with no knowledge of the construction, how many were already covered by the builder's own 90-test suite or its own adversarial self-review.
Collected by
An overlap analysis performed against the existing suite and self-review document after the verification findings were received.
Does not show
One verification pass on one codebase. It shows these mechanisms missed what that one found; it does not quantify how much any mechanism generally misses, and a different reviewer would have found a different set.
Sourcekemiller2002/SDE-Engineering-Trial-2-Greenfield-Construction / experiment-2b/INDEPENDENT-VERIFICATION.md at claude/greenfield-experiment-2b-replication-n8pgtqprivate repository

7, of which 4

Defects found, and how many needed the extra pass

Self-reported

Measures
Seven recorded defects. Three were found by the builder's own construction, testing and self-review; four were found only by the independent verification phase.
Collected by
Every defect logged with a stable id, its discovery mechanism, root cause, repair and regression evidence.
Does not show
A higher defect count here does not mean a worse build. It largely measures how many independent verification passes this build received compared with the one it is being read against.
Sourcekemiller2002/SDE-Engineering-Trial-2-Greenfield-Construction / experiment-2b/DEFECT-REGISTER.md at claude/greenfield-experiment-2b-replication-n8pgtqprivate repository

2 + 1 + 1 + 0

Defects, by the mechanism that found each

Self-reported

Measures
Two found by the type checker, one by a manual smoke test against real disk, one by adversarial self-review, and zero by the automated test suite.
Collected by
Recorded per checkpoint as each was found, with the finding mechanism named.
Does not show
Four mechanisms, four different results. This is a description of one build's defect discovery, not a ranking of mechanisms: the self-review found one because it looked for a shape the tests could not express.
Sourcekemiller2002/SDE-Engineering-Trial-2-Greenfield-Construction / experiment/TELEMETRY.md at claude/greenfield-engineering-experiment-2-ee44qz — T5 — Verified Implementationprivate repository

A fresh agent, with no knowledge of how a build had been constructed, reviewed a finished implementation that had already passed a 90-test suite, a strict type check with noUncheckedIndexedAccess and exactOptionalPropertyTypes, a dependency audit, an architecture check, and an adversarial self-review that included three mutation tests deliberately breaking shared guards to confirm they were load-bearing.

It found five defects. None had been caught by any of that. One was a result case declared in a type that no code path could construct — the type checker was satisfied, ninety tests were satisfied, and the contract was incomplete.

Independently, METR 2025 found the same shape in someone else's repositories: agent solutions passing reference tests and still failing merge-readiness review. Two research programmes, different codebases, same finding.

Verification mechanisms and their blind spots
MechanismRefusesCannot refuse
Type and exhaustiveness checkingUnrepresentable states, unhandled cases, signature driftCode that type-checks and does the wrong thing
Architecture and dependency checksLayering violations, inverted dependenciesCorrect layering around incorrect behaviour
Contract and boundary checksRepresentation collapse at a declared boundaryBoundaries nobody declared
Behavioural testsBehaviour the author thought to assertA check that passes for the wrong reason
Integration against a real boundaryPresent-but-inert implementations, wire-format mismatchesConditions the integration environment never produces
Independent adversarial reviewDeclared-but-unreachable outcomes, vacuous assertionsAnything the reviewer also fails to imagine
Each row's right-hand column is what some later mechanism has to cover. This is why Ordo asks for several mechanisms with different sensitivities rather than a higher number from one.

Why this matters operationally. If a green suite is your merge signal, and a green suite does not distinguish merge-ready work from work that merely passes, then raising test counts does not buy you what you think it buys. The fix is not more tests of the kind you have. It is at least one mechanism whose blind spot differs from theirs.

Limit. One verification pass on one codebase. It shows these mechanisms missed what that reviewer found; it does not quantify how much any mechanism generally misses. Every agent involved came from one model family, so a shared blind spot cannot be ruled out.

Conventional code goes quiet exactly where it matters most

The same domain was rebuilt under a deliberately ordinary persona — a competent professional developer reaching for mutable classes and bare primitives by default. Not a strawman, and the distinction matters: the finding is about type design, not carelessness.

~14

Call sites where a rename silently changed meaning

Self-reported

Measures
Sites in the conventional C# rebuild where duration was passed as a bare positional integer, so the same source text meant something six times different after the unit change.
Collected by
Counted by hand during the change, because no mechanism surfaced them. The compiler caught eight direct member accesses and none of these.
Does not show
An approximate count of sites requiring manual re-interpretation, not a defect count. Every one was correctly migrated in this trial — the finding is that nothing mechanical distinguished a correct migration from a wrong one, not that wrong ones shipped.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/EFFORT-LOG.md at 73a63f1ac319 — F1 — exact-minute recording + derived billingprivate repository

2

Values that survived the change correct by coincidence

Self-reported

Measures
Call sites left unchanged not because they were verified but because their literal happened to remain valid under the new unit.
Collected by
Identified by reading each site's intent during the manual migration pass.
Does not show
Two sites in one change in one codebase. It illustrates the failure mode rather than measuring its frequency.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/EFFORT-LOG.md at 73a63f1ac319 — F1 — exact-minute recording + derived billingprivate repository

0

Mistakes caught by the language

Instrumented

Measures
Mistakes in the conventional JavaScript rebuild caught by the language or its tooling rather than by a test or a person.
Collected by
Classified per mistake as it was found. A property rename across two production files produced zero errors, zero warnings and zero crashes.
Does not show
A property of JavaScript with no type checker configured, not a claim about JavaScript projects that use one.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/EFFORT-LOG.md at 73a63f1ac319 — Totals — the complete hodgepodge JavaScript buildprivate repository

When the unit of measure changed, renaming the duration field caught eight call sites in the compiler. Around fourteen more passed duration as a bare positional integer — where the literal 10 had meant ten six-minute units, sixty minutes, and now meant ten minutes. Identical source text, six times the duration, no compile error. The build was clean and all thirty tests passed while that was unresolved.

In the JavaScript rebuild, the language caught nothing at all, at any point, for any reason. A property rename across two production files produced zero errors, zero warnings and zero crashes. The program ran.

Against that, the state-structured builds: every ripple location surfaced all of themRipple sites found by the compiler rather than by searching, and in the F# trial 17Ripple sites surfaced in a single build across two root causes — each root cause showing every affected call site at once. Zero required a manual search.

Limit. Comparing the state trials against the conventional rebuilds is partly a comparison of persona, and the state trials' own reports say so. What is not a persona effect is the structural point below.

The difference, stated as numbers

The two tables below are the whole comparison. Everything else on this page is context for them. Every figure links to its own record — definition, how it was measured, what it does not show, and the file and section to check it against.

1. The same intended change, propagated four ways

The unit of measure changed: recording became exact to the minute, six-minute rounding moved to a derived billing view. The identical change was applied to the same domain in four implementations. The question is how many of the affected call sites the machine named, and how many a person had to find.

Call sites named by the machine versus found by hand, on one identical change
Implementation Size Sites the machine named Sites a person had to find Manual searches needed
Conventional C# 1,645 lines 8 of ~22 ~14 Every one of them, by hand
Conventional JavaScript 1,540 lines 0 of ~22 All of them A grep, run on suspicion
Ordo, C# — all of them None None
Ordo, F# — 17, in a single build None None

The C# row is the one to read carefully. Eight of roughly twenty-two sites were direct member accesses the compiler reported. The other fourteen passed duration as a bare positional integer, so the literal 10 went from meaning sixty minutes to meaning ten — identical source text, six times the duration, clean build, all tests passing. Two of those were correct by coincidence (2 of them). In the JavaScript rebuild the language named nothing at all; 8, from one root cause test failures caught the change instead, and only because those assertions compare numbers rather than reference the renamed property.

The two Ordo rows show no manual searching for this change. As whole-trial context rather than a cell in the table above: the C# state-system trial ran 18 repository searches in total, for every purpose combined, with 0 context expansions beyond its planned reading list.

2. Mistakes, by the mechanism that caught each one

This is where the popular version of the claim breaks. Raw mistake counts do not favour more static checking — the build with the least of it scored best. What differs is which mechanism did the catching.

Rework-driving mistakes and their catching mechanism, two conventional rebuilds
Caught by Conventional C# Conventional JavaScript
Total rework-driving mistakes 6 2
The compiler or the language 3 of 6 0
A test run 1 of 6 None counted — 8, from one root cause on the unit change, caught pre-green
A person re-reading the diff 3 of 6 1 of 2
Nothing — found by luck 0 1 of 2
Shipped undetected 0 0

Two things about this table that we corrected rather than presented cleanly.

The C# mechanism rows sum to seven catch-events over six mistakes, because F7's stale revision was caught twice — first by a pre-build read-through, then by the compiler. The rows do not partition, and are not presented as if they do.

The compiler figure was also published here as 4 of 6 and is now 3 of 6. The source log's tally of four included the eight rename sites from the unit change, which are the compiler propagating an intended change rather than catching a mistake — the log's own row for that requirement records zero mistakes shipped. Those eight are real and belong in table 1, where they now are. They were never a mistake count.

What the two tables together support, and nothing more: the conventional C# rebuild made 6 mistakes and the JavaScript one 2, at comparable size. Of the C# six, 3 of 6 were invisible to every mechanism and were caught only because someone deliberately re-read a diff before running it. Swapped string arguments, a stale revision inside a loop, a signature change hidden behind var — none of these is catchable by a compiler even in principle. In the state-structured builds the equivalent substitution is unwritable, because a duration and a time are different types. That is the claim. It is a claim about which failures remain possible, not about how many occur.

Why this table has two columns and not four. The two state-system trials did not log mistakes in this format — their records classify defects by class and report 0Runtime domain defects and 0Runtime domain defects runtime domain defects respectively, which is not the same measurement. Rather than convert between formats and present the result as like-for-like, the columns are left absent. Table 1 is the four-way comparison, because propagation was recorded the same way in all four.

Where the machine caught nothing

Five measured cases, all from experiments designed to find them. These are the boundaries of the claim above, and they are listed with numbers for the same reason the numbers above are: so the limit can be checked rather than taken on trust.

Measured cases where mechanical checking did not help
What was tested Result What it rules out
A boundary arm deliberately deleted 0 of 3 checks objected That the architecture notices missing handling
A boundary arm present but inert, against five purpose-built mechanisms 0 of 4 caught it That mechanisms built for this class catch this class
A wrong divisor in an arithmetic business rule none from either type system The strong form of the typing claim outright
A field rename, explicit domain versus competent baseline none measurable That explicit types propagate renames better in general
A pattern search for conversion sites 1 of 7 missed Searching as a substitute for compiler-reported propagation

And the one that cuts hardest, because it runs against the direction the method predicts: in the third controlled experiment, as-experienced mechanical discovery went 42.1% to 31.6% — lower after hardening, not higher — across 19 and 19 required change sites, while search operations fell 38 to 14 and repair loops 2 to 1. Discovery rate and engineering cost moved in opposite directions. The site does not have a resolved explanation for that, and the hypothesis it belongs to is open.

Some things are not measured — they are guaranteed

These are properties of the code, verifiable by reading it. They carry no confidence interval because they are not statistical claims.

A duration cannot be passed as a time

TimeOfDay and DurationMinutes are separate nominal types, with the source comment stating the reason: so a caller "cannot pass a duration where a time-of-day is expected and have it compile." The failure mode from the section above is not unlikely here. It is unsayable.

A missing case is a build error

The entry lifecycle is a closed set with exhaustiveness checking elevated to a build error. Adding a state does not risk a forgotten branch; it produces a failing build at every site that must now decide what the new state means.

No half-transitioned value is observable

Every command produces a new immutable value rather than mutating one in place. There is no public setter, so a caller holding a reference from before a command ran sees the pre-transition value — never a partially updated one.

A terminal state is tested, not assumed

Nothing leaves Superseded. Every guard refuses it and two acceptance criteria assert the refusal — so the constraint is verified rather than merely absent from the code, which is indistinguishable from an oversight.

Specification clarity is reachable, and it is the new bottleneck

arXiv 2605.01160 2026 concludes that under specification governance the constraint on velocity moves from generation to specification clarity. Two independent builds of the same frozen requirements tested whether that clarity is actually achievable by an agent.

58 / 58

Acceptance criteria implemented and traced

Self-reported

Measures
Acceptance criteria from the frozen requirements package with an implementation and a named test, mapped ID by ID.
Collected by
A traceability document mapping each criterion to the test covering it, written alongside the implementation.
Does not show
Traceability means every criterion has a test. It does not mean the tests are good: this build's own suite found zero new defects, and an independent reviewer of the replication found five things its equivalent suite missed.
Sourcekemiller2002/SDE-Engineering-Trial-2-Greenfield-Construction / experiment/REQUIREMENTS-TRACEABILITY.md at claude/greenfield-engineering-experiment-2-ee44qzprivate repository

1 of 41

Requirements-scope divergences between two independent builds

Derived

Measures
Across 12 product requirements, 20 business rules and 9 open questions, how many were handled differently by the two builds.
Collected by
A per-dimension comparison of both codebases and both requirements inventories, performed after this build's own results were frozen.
Does not show
Two builds by the same model family with the same tooling. Convergence between similar systems is weaker evidence than convergence between genuinely different ones, and two runs are not a sample.
Sourcekemiller2002/SDE-Engineering-Trial-2-Greenfield-Construction / experiment-2b/ARCHITECTURAL-CONVERGENCE.md at claude/greenfield-experiment-2b-replication-n8pgtq — G. Convergence scorecardprivate repository

22 and 22

Source files in each of two independent builds

Instrumented

Measures
Source file counts from two agents building the same frozen requirements without seeing each other's work.
Collected by
Counted directly on both working trees during the comparison.
Does not show
The comparison warns explicitly against reading physical similarity as semantic convergence: the identical count masks real differences in how each build maps semantic clusters onto files.
Sourcekemiller2002/SDE-Engineering-Trial-2-Greenfield-Construction / experiment-2b/ARCHITECTURAL-CONVERGENCE.md at claude/greenfield-experiment-2b-replication-n8pgtq — C. Physical architecture convergenceprivate repository

Both builds implemented all 12 product requirements, all 20 business rules and all 58 acceptance criteria, with an ID-by-ID mapping from each criterion to the test covering it. Both preserved all nine open questions as unresolved rather than guessing past them. Neither had seen the other's work.

They converged on the same seven entities, the same three state machines, the same transition set, a mathematically identical overlap formula and an identical billing formula — and independently arrived at the same architecture for deriving capabilities from the predicates the transitions enforce, documenting the reason in nearly the same words. Across 41 requirement-level decisions they differed on one, and that one was a scope question about what to build rather than a disagreement about a rule.

Cold-start reconstruction was also tested directly: 10 of 10Cold-start questions answerable without opening source — what the application does, where authoritative state lives, which transitions are legal, where each workflow is implemented and how it is tested, all answerable from the generated documents without opening a source file.

Limit. Two builds are a replication, not a sample, and both came from the same model family — convergence between similar systems is weaker evidence than convergence between different ones. The cold-start figure was self-assessed after a documentation gap had been closed, not tested on an actual fresh reader.

Requirements-first construction held up

0

Runtime domain defects

Self-reported

Measures
Defects in domain logic reaching a run, as distinct from test-authoring or language-tooling errors.
Collected by
Counted across the whole trial, with all three repair loops classified and none of them a domain-logic error.
Does not show
A single uninterrupted first pass with no later requirement change to force rework. The trial's own report declines to read this as evidence that the architecture reduces rework.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/c-sharp-state/EXPERIMENT-REPORT.md at 73a63f1ac319 — G. Metricsprivate repository

0%

Rework ratio

Derived

Measures
Proportion of completed work replaced because earlier work turned out to be wrong.
Collected by
Derived from the per-file classification: no file was rewritten, and no semantic decision was revised.
Does not show
No later requirement arrived to force rework during this trial, so this is the absence of a cause, not evidence of resistance to one.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/c-sharp-state/EXPERIMENT-REPORT.md at 73a63f1ac319 — G. Metricsprivate repository

0

Context expansions beyond the planned reading list

Self-reported

Measures
Occasions where in-hand context proved insufficient and the agent had to widen its search to proceed.
Collected by
Counted during the trial.
Does not show
One agent working from a specification it had itself just produced, which is a favourable condition. It does not measure what a fresh agent would need.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/c-sharp-state/EXPERIMENT-REPORT.md at 73a63f1ac319 — G. Metricsprivate repository

Recovering the requirements, modelling the states, and only then implementing produced a first pass with no runtime domain defects and nothing rewritten because earlier work was wrong. All sixteen domain files touched contained semantic decisions; none contained only mechanical propagation. Eighteen searches across the entire trial, with no occasion where in-hand context proved insufficient.

Limit, and it is a real one. This was a single uninterrupted pass with no later requirement change to force rework. The trial's own report is explicit that Semantic Change Coverage is therefore not applicable rather than zero, and that a fair claim about reduced rework would need a follow-up change-task trial it did not run. We are not making that claim.

What we tested and did not find

The most tightly controlled experiment in this evidence base was built to test whether explicit domain types reduce the cost of propagating a change. It held feature scope, code quality, the change itself and the agent constant, varying only the presence of opaque types, with falsification criteria set in advance.

It refuted the hypothesis in its stronger form.

none measurable

Difference between type systems on field renames

Instrumented

Measures
Whether an explicitly-typed domain propagated a field rename more completely than a competent conventional baseline.
Collected by
The identical change was applied to both and every call site counted. Both caught every site automatically.
Does not show
This is a null result, published because the experiment was designed to be falsifiable. It does not mean types are useless; it means this particular change class does not distinguish them.
Sourcekemiller2002/time-entry-state-machine / research/experiments/EX-TE-2026-0001--conventional-baseline-comparison.md at 73a63f1ac319 — Analysisprivate repository

none

Help from either type system on arithmetic business rules

Instrumented

Measures
Whether a wrong unit conversion embedded in an expression was caught by either implementation's type system.
Collected by
The same change was applied to both. A wrong divisor compiles cleanly in both, because the value is a bare number until it crosses a smart constructor.
Does not show
This directly contradicts the stronger form of the hypothesis the experiment tested. It is on this site because it is true, not because it helps.
Sourcekemiller2002/time-entry-state-machine / research/experiments/EX-TE-2026-0001--conventional-baseline-comparison.md at 73a63f1ac319 — Analysisprivate repository

1 of 7

Conversion sites a pattern search missed

Instrumented

Measures
Sites needing change that a grep for the conversion pattern failed to find, because the same rounding was written as a division by 360 rather than by 6.
Collected by
Found only by a second, deliberate search prompted by suspicion that the first pass was not exhaustive.
Does not show
The report traces this to inlined conversions rather than to the type system, and notes the centralising discipline that avoided it is achievable in either language.
Sourcekemiller2002/time-entry-state-machine / research/experiments/EX-TE-2026-0001--conventional-baseline-comparison.md at 73a63f1ac319 — Resultsprivate repository

On field renames, both the conventional and the explicitly-typed implementation caught every call site automatically — no measurable difference. On arithmetic business rules embedded in expressions, neither type system helped: a wrong divisor compiles cleanly in both, because the value is a bare number until it crosses a smart constructor.

The one asymmetry observed was a discovery failure, not a type failure — a pattern search missed a site where the same rounding was written as a division by 360 rather than by 6. And the report traces even that to architecture rather than language: the explicitly-typed domain routed arithmetic through named accessors, so there were fewer raw sites to miss. That discipline is achievable in either language.

The hypothesis record remains open rather than supported. We publish this because an evidence base that only contains its own confirmations is not an evidence base.

What none of this establishes

The research behind it

Independent work establishing the problem, with what each source does and does not support:

Independent research this site relies on
StudySourceFindingDoes not establish
Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer ProductivityMETR (Becker, Rush, Barnes, Rein), 2025Sixteen experienced maintainers completed 246 real issues in repositories they knew well and were 19% slower with AI available, having forecast a 24% speedup and still believing afterwards they had been 20% faster.Sixteen developers, selected open-source projects, early-2025 tooling and self-reported time. The authors later judged a follow-up estimate unreliable because developers unwilling to work without AI declined to participate.
State of AI-assisted Software Development (2025 DORA report)DORA / Google Cloud, 2025Higher AI adoption now correlates with higher delivery throughput and, at the same time, with higher delivery instability — more change failures, more rework and longer recovery. DORA attributes the instability to change volume outrunning the control systems meant to absorb it.Survey-based observational associations, not causal measurement. It describes a correlation across organisations, not an effect any single team should expect.
Impact of Generative AI in Software Development (2024 DORA report)DORA, 2024Every 25% rise in AI adoption was associated with roughly a 1.5% fall in delivery throughput and a 7.2% fall in delivery stability, while individual satisfaction and self-reported productivity rose.Superseded in part: the 2025 report found the throughput relationship had reversed. Only the instability direction persisted. Cited here for the divergence between individual perception and system outcome, not for its throughput figure.
Holistic review of agent solutions on real repository tasksMETR, 2025Across eighteen real tasks in two mature repositories, agent solutions could pass reference tests and still fail a holistic merge-readiness review on testing, documentation, formatting, typing or general quality.Eighteen tasks in two repositories, with merge-readiness judged by manual review rather than by an objective standard.
The Productivity-Reliability Paradox: Specification-Driven Governance for AI-Augmented Software DevelopmentarXiv 2605.01160, 2026Telemetry across more than ten thousand developers showed 98% more pull requests, 91% longer review times and flat delivery metrics. The authors reconcile the contradictory productivity literature through task abstraction, codebase maturity and developer experience, and argue that under specification governance the bottleneck moves from generation to specification clarity.A framework paper synthesising other people's measurements. It proposes a governance model rather than reporting a controlled trial of one.
Randomized controlled task: Copilot on a bounded HTTP-server implementationGitHub, 2022Ninety-five professional developers completed a bounded, automatically scored greenfield JavaScript task 55% faster with AI assistance, with a 78% completion rate against 70% for the control group.Run and published by the tool vendor, on a bounded greenfield task with automatic scoring. It demonstrates that speedup is possible in that setting, not that it generalises to maintenance work.
Expertise reversal: guidance effects depend on prior knowledgeEducational-psychology randomized experiment, 2026Instructional guidance and redundancy that help a newcomer can add extraneous cognitive load for an expert, so a fixed template can simultaneously over-support one reader and under-support another.Established in instructional settings rather than in software engineering. It is a reason to expect a cost, not a measurement of that cost in a codebase.
Contextual resumption cues and task-completion successSurvey of 371 programmers with a controlled follow-up study, 2026Automated contextual cues produced roughly twice the task-completion success of note-taking alone when programmers resumed interrupted work.A laboratory result with older tooling. It supports the idea of state-reconstruction aids without establishing that any particular aid works in production.
The SPACE of Developer ProductivityForsgren, Storey, Maddila, Zimmermann, Houck, Butler, 2021Developer productivity spans satisfaction, performance, activity, communication and efficiency, and cannot be reduced to any single metric without distorting what it measures.A framework rather than a measurement. It tells you which dimensions to cover, not what good looks like on any of them.

Our own trials, with objective, method, findings, refutations, anomalies and limits recorded per experiment: the experiment records → and the full map of what is supported, provisional, contradicted and open →