4.3 Validating Change

Every engineering process eventually asks the same question: what evidence is sufficient to accept this change? Code review, testing, static analysis, operational measurement, and expert judgment answered that question long before coding agents arrived. Commodity implementation does not make those techniques obsolete. It makes them more important, because changes can now arrive faster than human inspection can scale.

Validation begins with an obligation. If the obligation is settled, evidence can test whether the change satisfies it. If the obligation is still a hypothesis — whether users want the feature, which workflow they prefer, which tradeoff is acceptable — no test suite can manufacture the missing product knowledge. In that regime the evidence is experimental. MAGE can govern the experiment and preserve known constraints; it cannot turn an open question into a mechanical truth.

4.3.1 Independent Evidence

To validate a change is to assemble evidence that bears on its obligations and decide what consequence that evidence should have. The producer's own report is rarely enough. A human says the change is correct; an agent says the tests pass; a tool announces completion. Each claim may be useful, but the strongest assurance comes from evidence generated independently of the judgment seeking admission.

For consequential changes, prefer evidence that can challenge the producer's own claim rather than relying on self-report alone. Where the consequence warrants it, place admission authority outside the producer's ability to redefine success.

That evidence can come from several sources. A model may expose a system-level invariant. A test may exercise a behavior. A compiler or type system may reject an illegal state. A reference implementation may supply a differential oracle. A metric may reveal degradation. A human reviewer may decide a property that remains judgment-laden. MAGE does not require that all validation route through one kind of representation. It requires that the obligation and the evidence be adequate to the claim.

4.3.2 Build the Oracle

An oracle is whatever supplies the judgment against which the observed result is evaluated. An oracle is stronger when its judgment is sufficiently independent of the implementation being judged and explicit enough that its verdict has a stable meaning. Sometimes that oracle is a simple property: the output is an ordered permutation of the input. Sometimes it is a type or schema. Sometimes it is a reference implementation. Sometimes it is a human rubric.

SOFTWARE ENGINEERING

Inset — The oracle problem

Software testing has a longstanding asymmetry: executing a program can be much easier than deciding whether the result is correct. Testing research calls this the oracle problem 11. Earl T. Barr et al., “The Oracle Problem in Software Testing: A Survey,” IEEE Transactions on Software Engineering 41, no. 5 (2015): 507–25.. An expected output supplies an easy oracle for some cases; complex behavior may instead require properties, reference implementations, metamorphic relations, models, runtime evidence, or human judgment.

Commodity implementation widens the asymmetry. Agents can cheaply produce implementations, variants, and test inputs, but producing more candidates does not supply an independent basis for judging them. As generation becomes cheaper, the engineering bottleneck moves toward stating what must hold and constructing evidence capable of distinguishing acceptable realizations from unacceptable ones.

Existing behavior can stand in for a surprising amount of written specification. In a compatibility port or a structure-preserving migration, a reference implementation supplies an executable oracle: challenge a new realization with the same inputs and compare it against known behavior. Tests, benchmarks, compatibility suites, and production traces close the target further. The implementation problem may stay enormous, but much less of the engineering question remains open.

Explicit models matter because they can supply oracles for properties that do not exist at the level of one input/output example. A state machine can define legal transitions; an architectural graph can define permitted edges; a performance model can define an acceptable bound. The same representation that helps an agent reason about the system can therefore become input to an independent validator. Modeling enlarges the semantic reach of an oracle, but an oracle need not come from a model.

This is where generative validation becomes powerful. An example test pins one point: given this input, expect that output. A property states a law over a domain and lets a generator search for a counterexample. A stateful model can extend the same idea over sequences; a bounded concurrency model can extend it over interleavings. The useful progression is not "simple test to sophisticated test." It is from one known case to a claim over a space. Figure 4.3-1 draws the difference.

An example-based test pins one point; a generative test models the whole input space On top, an example-based test maps one chosen input to one expected output — a single labelled point. Below, a generative test drives a generator that produces inputs drawn from the space into a check of whether the specification holds; on a failure the framework shrinks the input to its minimal or spec-point cause. A dotted arrow marks the shift from pinning one point to modelling the whole space. Example-based test one chosen input one expected output ✓ from one pinned point to the whole space Generative test generator inputs drawn from the space specification holds? no shrink / RCA to the minimal or spec-point cause
Figure 4.3-1. A Point and a Space. An example pins one chosen case; a generative test states a property over a domain and searches for a counterexample. Use the broader claim when the obligation itself is broad enough to support it.

A failing example invites a local repair, because the evidence names one point: patch the branch that makes that input pass and the example goes green. A broader property makes that repair easier to falsify if the underlying class remains open — the generator keeps drawing neighbours that still exercise the law, so a branch-cut that satisfied one input fails the next. When the defect exposes a general law, preserve the law rather than only the example that revealed it.

The techniques that generate evidence this way share one loop — generate, execute, judge, shrink or diagnose — and differ in the generator that makes the inputs and the oracle that judges them. None is a maturity rung. Choose the generator and oracle that match the property you are trying to falsify (Inset 1 lays them side by side).

SOFTWARE ENGINEERING

Inset — Example, property, fuzzing, model-based: what changes?

Four ways to produce evidence, one shared loop — generate → execute → judge. They differ in where the inputs come from, where the verdict comes from, and what each is best at.

Table 4.3-1.
TechniqueInputs come fromOracle comes fromBest at
Example testengineer-chosen examplesthe expected output, written downknown cases, regressions
Property testan authored input domainan invariant the output must obeylaws over many valid cases
Fuzzingmutation and adversarial generationa robustness contract, plus richer auxiliary oraclesmalformed and edge inputs
Model-based / statefulmodel-generated actions and statesan explicit behavioral modelsequences, protocols, state

Read each row left to right: the oracle defines what counts as success; the generator determines how the technique searches for evidence. The boundary is not even sharp: some systems combine an explicit input-language grammar with semantic constraints, generating high-diversity inputs while keeping tight control over what each one means 22. José Antonio Zamudio Amaya et al., “FANDANGO: Evolving Language-Based Testing,” in “Proceedings of the ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA 2025),” special issue, Proceedings of the ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA 2025) (New York, NY), 2025, https://doi.org/10.1145/3728915. — a hybrid that sits between the property and fuzzing rows.

These are not rungs on a maturity ladder. Choose the technique whose generator and oracle match the engineering claim.

4.3.3 Generate Falsifying Evidence

Let the engineering claim choose the search. Not every obligation wants generated test inputs, and not every consequential property wants formal verification. Use the cheapest mechanism that can genuinely falsify the claim. Figure 4.3-2 sorts the claim kinds.

Let the claim choose the search The kind of claim you are trying to establish selects the kind of falsifying evidence. A one-or-many-inputs claim about input to output is checked by examples, property tests, or fuzzing, and is refuted by a counterexample input. A reachable-states claim about sequences or races is checked by explicit-state model checking, and is refuted by a counterexample trace. A temporal-behavior claim about what eventually or always holds is checked by temporal model checking, and is refuted by a counterexample execution. Prefer structural prevention before any of these when the invalid state can simply be excluded. WHAT CLAIM ARE YOU TRYING TO ESTABLISH? ONE / MANY INPUTS input → output REACHABLE STATES sequences / races TEMPORAL BEHAVIOR eventually / always examples / property tests / fuzzing explicit-state model checking temporal model checking counterexample input counterexample trace counterexample execution Prefer structural prevention before any of these when the invalid state can simply be excluded.
Figure 4.3-2. Let the claim choose the search. Input/output properties, reachable-state invariants, and temporal properties require different kinds of falsifying evidence. Structural exclusion is preferable when the invalid behavior can be removed from the admissible space entirely.

Start with prevention. If the forbidden state can be removed structurally, remove it. DocAble's pervasive work-item ownership rule is enforced by a database compare-and-set: an update succeeds only while the row remains in the expected prior state. Concurrent claimants race on the same transition, and only one can win. For that local ownership property, the runtime constraint can enforce the required transition directly; a temporal specification would answer a broader question than the one being asked.

When the property lives in interleavings, reduce the relevant state until it can be explored. DocAble's in-flight lease has this shape: a worker can appear stale and be reclaimed, another worker can acquire a fresh epoch, and the first can later wake and attempt release. The ownership question does not require the rest of the implementation. A reduced transition model retains only lifecycle state, lease epochs, reclaim, release, and the variables needed to state the invariants.

A small explicit-state checker exhaustively explores the resulting bounded state space. Separate checks compare selected production paths with the abstract model. These establish different things: exhaustive exploration searches the bounded model; the implementation checks provide evidence of correspondence. They do not establish formal refinement.

Some obligations cannot be falsified by a finite bad state. DocAble's serverless recovery path carries the temporal requirement that every submitted job eventually reaches a terminal state. A finite test can show that one execution terminated; it cannot show that no fair execution can remain stranded forever. For such liveness properties, DocAble uses small TLA+ specifications and TLC to reason about the temporal model. The representation and its checker answer a different question from the database CAS and the finite-state safety checker.

The three cases make the rule concrete: make violation impossible when the action space can be closed; exhaustively search a bounded model when the risk lives in finite interleavings; use temporal model checking when the obligation ranges over executions. None is automatically stronger engineering. Strength means adequate evidence for the claim that matters.

When a generated input exposes a defect, fix the stable obligation rather than merely the seed. The durable repair should close the class of behavior exposed by the counterexample whenever that class can be stated. A one-byte crash may reveal a parser invariant; a bad transition may reveal a missing state rule; a valid-but-unusual producer may reveal that the authored input grammar was incomplete.

Where available, real producers are valuable sources of dialects and edge cases that a synthetic generator may miss. Build richer synthetic generation when the engineering claim justifies the additional model and upkeep.

Three properties, three mechanisms

The important difference is not the tool. It is the shape of the property.

4.3.4 Name the Obligation Set Before Claiming Coverage

Coverage answers a question about a population; the population must be named before the percentage has engineering meaning.

Ordinary test coverage starts from the implementation, or from the tests that already exist. It can tell you a line was never executed. It cannot tell you that an important behavior has no test at all, because nothing first named that behavior as an obligation. Implementation-derived coverage cannot reveal an obligation that was never represented in the population being measured.

Explicit models can supply the missing census. A state model enumerates the transitions that require evidence. An architectural model enumerates the forbidden or permitted edges. An error model enumerates the failure paths. A requirement model enumerates the claims that must be discharged. Derive that set from the models — every seam that owes a fuzzer, every failure edge that owes an injection test, every invariant that owes a checker — and a missing test becomes a named finding rather than an absence nobody notices.

From there, the assurance sequence is straightforward. Figure 4.3-3 lays it out: name the model, derive the obligations it implies, take the census, choose evidence appropriate to each claim, and only then claim coverage against that set.

From models to evidence — a model derives both current facts and the obligation set. A green model-or-specification box splits into two branches. The left branch derives facts and relations, ending in a current view. The right branch derives obligations — what must hold — into an obligation census. The census flows into a dashed rust select-evidence step, which fans into three neutral evidence artifacts: test, lint, and search or proof. These merge into a green claim-coverage box. An uncovered claim flows on to a dashed red visible-debt box. The point: coverage is meaningful only after the obligations are named, and each claim is matched to evidence appropriate to its shape. II · From Models to Evidence MODEL / SPECIFICATION DERIVE FACTS & RELATIONS DERIVE OBLIGATIONS what must hold? CURRENT VIEW OBLIGATION CENSUS SELECT EVIDENCE for claim shape TEST LINT SEARCH / PROOF CLAIM COVERAGE uncovered claim? VISIBLE DEBT Coverage is meaningful only relative to a named population.
Figure 4.3-3. From models to evidence. Coverage becomes meaningful only after the engineering obligations have been named. Explicit models can derive that population; tests, lints, searches, proofs, and human review then supply evidence appropriate to each claim.

With the census in hand, a high aggregate percentage stops being reassurance and becomes a place to look: this invariant has no exercising test.

4.3.5 Did the Search Cover the Claim?

Generative validation adds an honesty question that a small example suite can often avoid: did the campaign search the semantic region the claim is about? Code coverage answers where execution went. Input-space coverage answers what kinds of cases the generator produced. Neither alone proves the relevant obligation was exercised.

Where traceability exists, a more semantically targeted question becomes possible: which model claims were actually exercised? Follow an invariant, transition, or architectural relation to the code that realizes it, then ask whether the campaign reached that implementation under evidence relevant to the claim. A high aggregate percentage can then become a named gap: this invariant has no exercising test. The degree question — how much coverage is enough — belongs to the metrics treatment in Operating MAGE, which owns the discipline to measure one level deeper than a raw percentage.

Coverage remains evidence about the search, not proof of correctness. Its purpose is to keep claims such as "we fuzzed it" or "the model is tested" from becoming ceremonial. Figure 4.3-4 draws the loop: a generator makes inputs, the system runs, an independent oracle judges each outcome, a counterexample feeds back to shrink or diagnose, and coverage asks whether the search reached the claim before refining the generator.

Generate, judge, search again — around one independent oracle A left-to-right loop. A generator makes inputs; the system under test runs them; an independent oracle judges each outcome. The oracle draws its verdict from one of several independent sources — a declared property, a robustness contract, a reference implementation, or a structured model — none of which is the system being judged. A failing outcome becomes a counterexample, shrunk to its minimal form or diagnosed to the stable obligation it violated. That outcome flows into coverage, which asks whether the search ever reached the semantic region the claim is about. Two dashed loops close the cycle: one refines the generator, and where a traceability graph exists, one joins model-claim coverage back to the claim. generator makes inputs system under test independent oracle judges the outcome property · contract · reference impl · model · human counterexample shrink / diagnose to the stable obligation coverage: did we reach the claim? input-space · line/branch · model-claim refine the generator model-claim coverage joins back — where a trace exists
Figure 4.3-4. Generate, Judge, Search Again. One loop, whatever the oracle's source: a generator makes inputs, the system runs them, an independent oracle judges each outcome, a counterexample feeds back to shrink or diagnose, and coverage asks whether the search reached the region the claim is about — refining the generator, and where traceability exists joining model-claim coverage back to the claim. The oracle may be a declared property, a robustness contract, a reference implementation, or a structured model; the loop does not care which.

4.3.6 Give the Verdict the Right Consequence

Validation may report or gate. Where a verdict should control admission, place that authority outside the producer's discretion. At consequential boundaries, consider re-deriving evidence whose freshness or independence matters to the admission decision rather than relying automatically on an earlier marker. A fuzz campaign may run nightly and report counterexamples without controlling merge; a cost validator may stay advisory; a security invariant may deserve immediate refusal. Authority is a separate design decision from evidence quality.

When such a campaign carries gating authority, the environment evaluates the obligation rather than relying on the producer's previous report.

4.3.7 Two Boundaries for Evidence

Part III gave a placement rule for authority: evaluate an obligation at the earliest boundary where it becomes legible and enforceable. That catches a problem close to its cause. A malformed brief should be rejected before an agent spends an hour acting on it. A structural violation visible at compile time should not wait for deployment. Early evidence shortens the feedback loop and keeps later work from compounding a defect that was already knowable.

Consequential work often deserves a second boundary: re-evaluate at the last safe point before the consequence becomes difficult to reverse. The two rules do not oppose each other. They answer different questions. The first asks: when can this property first be decided honestly? The second asks: what is the last point at which stale or invalid evidence can still be caught before the consequence?** The security analogy is time-of-check to time-of-use (TOCTOU): a property established at one instant may no longer hold when the protected action occurs because relevant state changed in between. The problem here is broader than the classical TOCTOU race, but the engineering instinct is the same. Early checks establish defects cheaply; a consequential boundary may still need fresh evidence about the state actually being admitted.

Figure 4.3-5 draws the span between the two.

Two evidence boundaries — earliest legible, and last safe before consequence. A horizontal timeline runs from work begins on the left to consequence on the right. Two rust diamond markers sit on the axis. The left diamond is the earliest legible boundary, where a property is caught cheaply near its cause. The right diamond is the last safe boundary, where required evidence is re-established before exposure. Between them, a note reads: relevant state may change between checks. The two boundaries answer different questions — when can this be decided honestly, and what is the last point a stale check can still be caught. work begins consequence relevant state may change between checks EARLIEST LEGIBLE BOUNDARY catch cheaply near the cause LAST SAFE BOUNDARY re-establish what must hold
Figure 4.3-5. Two evidence boundaries. Evaluate a property as soon as it can honestly be decided, but for consequential work, a later boundary may re-establish evidence whose freshness matters before admission or exposure. Early evaluation limits wasted work; final evaluation protects against stale evidence and intervening change.

The second check is not a substitute for the first, and it need not repeat every earlier check. Where a second boundary is warranted, re-run or otherwise re-establish the evidence whose freshness matters to admission. A test result recorded hours ago describes the revision that produced it. A review verdict describes the change that was reviewed. A deployment rehearsal describes the configuration it exercised. If relevant state can change before admission, the evidence can cease to describe the artifact now crossing the boundary — a recorded claim is a statement about the past, not the present, and it rots as sibling work churns the ground under it.

Done is a claim, not a stored fact. At a consequential boundary, ensure that the evidence still justifies the consequence; where freshness cannot otherwise be established cheaply, re-derive the relevant evidence rather than trusting a stale green checkmark. The gain compounds with velocity: the more often a system ships, the more often an un-gated build reaches someone, so a cheap re-check at the last safe boundary is worth more, not less, as release frequency rises.

4.3.8 Why Abundance Changes the Economics

None of these techniques is new. Property-based testing, fuzzing, static analysis, model-based testing, independent review, and automated admission all predate coding agents. What changed is the relative price of implementation and inspection. When implementation was scarce, human attention could sit close to every change. When implementation becomes abundant, repeatable assurance mechanisms become increasingly valuable because human inspection does not scale with implementation volume.

The engineer does not disappear from validation. Human judgment moves toward the decisions for which it has the highest marginal value: choosing obligations, designing representations, selecting evidence, calibrating validators, deciding which verdicts deserve authority, and resolving the cases the environment cannot decide honestly. The old techniques become more central because the economics around them changed.

Worked Examples

Takeaway. Separate producer from grader. Generate evidence built to falsify the claim, and place admission where the producer cannot redefine success.

Works Cited

  1. Barr, Earl T., Mark Harman, Phil McMinn, Muzammil Shahbaz, and Shin Yoo. “The Oracle Problem in Software Testing: A Survey.” IEEE Transactions on Software Engineering 41, no. 5 (2015): 507–25.
  2. Zamudio Amaya, José Antonio, Marius Smytzek, and Andreas Zeller. “FANDANGO: Evolving Language-Based Testing.” In “Proceedings of the ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA 2025).” Special issue, Proceedings of the ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA 2025) (New York, NY), 2025. https://doi.org/10.1145/3728915.
© James C. Davis, 2026–present