Examples

What this looks like in code

Eight worked examples, in the order a reader usually needs them: what an explicit state buys, what a transition costs, what changes for an agent, and then the four failures that shaped the method. Every one is drawn from a repository cited on this site rather than invented to illustrate — where an example is simplified for reading, it says so.

C# walkthrough

See the current method as code.

The examples on this page explain measured cases. The dedicated C# walkthrough goes one step further and shows explicit state, nominal types, named transitions, available-action projection, evidence and coverage gates, host-supplied Capability, obligations, and Unknown-effect reconciliation in one language.

Open Ordo in C#

1. An illegal state, and its removal

A conventional time entry. The states are implied by which fields are set:

type TimeEntry = {
  id: string
  active: boolean
  voidedAt: string | null
  supersededBy: string[] | null
  splitFrom: string | null
}

Four fields, sixteen combinations, three of which mean anything. Nothing prevents { active: true, voidedAt: "...", supersededBy: ["..."] }, and every function reading this record has to decide what that would mean.

The same domain with the state named, as one of the two independent builds modelled it:

type TimeEntry =
  | Recorded   of Common
  | Voided     of Common * voidedAt: Instant
  | Superseded of Common * supersededBy: EntryId list

supersededBy now type-exists only where it means something. The illegal combination is not rejected at runtime; it cannot be written down.

Rendered here in a neutral syntax. The build this is drawn from is TypeScript and uses a discriminated union keyed on status; the other independent build of the same requirements chose the flat shape above and prevented the combination with construction discipline plus a load-time validator instead. Both are covered on the state page.

Time entry lifecycle: three states and four legal transitions A time entry is created into the Recorded state. Recorded can move to Voided, and Voided back to Recorded. Recorded can move to Superseded when the entry is split or merged. Superseded is terminal: no transition leaves it. create void restore split or merge Recorded Voided Superseded terminal
The lifecycle implemented independently by three separate builds of the same requirements. Nothing leaves Superseded: every guard refuses it, and two acceptance criteria assert the refusal rather than relying on its absence from the code.

2. A transition, end to end

  1. 1Current stateThe named state the entity is actually in — not a combination of flags a reader has to infer.
  2. 2Requested actionA named action, not an arbitrary field write.
  3. 3Capability checkIs this action one the current state permits at all? If not, the request is refused here.
  4. 4Evidence checkIs the basis for the transition present and valid?
  5. 5Policy checkDo the business rules covering this action hold for these particular values?
  6. 6Legal transitionOnly now does state change, and only to a state the model declares reachable from the current one.
  7. 7New state, obligations, effectsThe resulting state, what must still happen for the transition to be complete, and the external effects requested as data rather than performed in place.
A requested action is checked against the current state before it can become a new state. Each gate refuses with a named reason rather than throwing or returning null.

Applied to splitting a time entry, as the measured build implements it:

Current state       Recorded
Requested action    split at minute 43
Capability check    is split legal from Recorded?         yes
                    (same predicate the transition uses as a precondition)
Evidence check      is minute 43 strictly inside the interval?
Policy check        is the resulting duration above the minimum?
                    is the referenced project still active?
                    is the referenced person still active?
Legal transition    Recorded -> Superseded
New state           the original entry, Superseded, with supersededBy set
                    two new entries, each Recorded
Obligations         the day's attestation, if any, is no longer current
Effects             one write to the record store, returned as data

Each check refuses with a named reason. A split at an interval endpoint is refused with a specific diagnostic — and both independent builds produced semantically identical refusals for that case, under different names, confirmed by running both systems.

3. What constrained agent action means

The difference is not politeness. It is the size of the space the agent is choosing from.

Unconstrained

"Fix the entry for Tuesday"

The action space is every file in the repository and every field on the record. The agent must infer what "fix" means, find where entries are written, and decide which write is appropriate. Nothing tells it that some of those writes produce a state the domain considers impossible.

Constrained

"Request a capability legal in this state"

The domain reports which actions are legal for this entry right now. The agent chooses one of those. An action absent from the report is not an action it can attempt badly — there is no function to call.

The measured build reports capabilities per entry and per project, computed from the same predicates the transitions enforce. An agent that asks the domain what is legal cannot construct an illegal request, because the illegal request is not in the answer.

  1. 1Work item and acceptance criteriaThe requested change starts with explicit intent and conditions that can be checked.
  2. 2Semantic mapThe repository points to the semantic area and authority that own the decision.
  3. 3Declared feature contextState, transitions, contracts, effects, interfaces, and tests for the feature are locally discoverable.
  4. 4Mechanical feedback firstCompiler, architecture, contract, and structural checks expose required propagation before broad search.
  5. 5Expand only when evidence says context is insufficientSearch is an escalation mechanism, not the default navigation strategy.
  6. 6Heterogeneous verificationBehavioural, integration, and independent review cover failure classes the earlier mechanisms cannot.
  7. 7Record evidence and unresolved obligationsThe work leaves behind what ran, what was established, what remains open, and what the evidence does not prove.
Ordo treats repository context as something to route and verify, not something every engineer or agent should reconstruct by exploration.

What this does not do. It constrains the action space; it does not make the chosen action correct. In the paired trial, both agents implemented a change that passed every mechanical check on both architectures and did the wrong thing. Constraint and correctness are different problems.

4. Finding the change surface without reading the codebase

A request arrives: the minimum splittable duration changes. Under Ordo the route is deterministic — repository map to semantic area, semantic area to authority, authority to the single predicate that decides it. The predicate is named, it is called by the transition as a precondition and by the capability projection as a report, and changing it changes both.

The measured alternative is what happens without that route. In the baseline condition of the paired trial, finding the sites for one change took 38 to 14Search operations repository search operations, against 14 in the hardened condition.

One paired trial, two agents whose investigation strategies differed. Unique files inspected did not drop the way search operations did. Classified provisional (CL-005).

5. A boundary defect, reproduced deliberately

A new case is added to a closed set of observation kinds. The domain type gains a case, and the compiler names the sites that must handle it — eight of twelve. The other four are outside its reach:

domain     type ObservedValue = ... | VitalSignObserved of ...   compiler names it
database   CHECK (kind IN ('lab','imaging','procedure'))        silence
wire       "kind": "vital_sign"                                  silence
fixtures   sampleFor : ObservedValue -> Sample                   silence until enumerated

Each silent site is a copy of the same fact with nothing checking that the copies agree. Experiment 1 measured one such fact duplicated four times and another twice. The hardening built in Experiment 2 closed each of these individually — a constraint-agreement test for the first, a single-source discriminator for the second, a fixture forced to a compile error for the fourth.

8 of 12

Required sites found by the compiler alone

Self-reported

Measures
The share of required handling sites for a new closed-alternative case that a compiler exhaustiveness error pointed at directly — 66.7%.
Collected by
Each site was classified as it was discovered, as either a compiler error or manual investigation, during the implementation itself.
Does not show
One change class — a new case in a closed alternative — on one architecture, in one trial. It says nothing about change classes the type system does not model, and the session classified its own discoveries.
Sourcekemiller2002/state-directed-engineering / research/evidence/EV-HN-2026-0003--experiment-1-boundary-amplification.md — Key figures

66.7% to 100%

Mechanical discovery rate after hardening

Self-reported

Measures
The share of required sites reported by a machine rather than found by looking, before and after five targeted hardening mechanisms.
Collected by
Same classification method as Experiment 1, applied to a new case on the hardened architecture.
Does not show
100% is measured against the specific blind spots these five mechanisms were built to close. Experiment 3 showed the figure does not transfer to a tier the hardening does not cover, where it fell well below this.
Sourcekemiller2002/state-directed-engineering / research/evidence/EV-HN-2026-0004--experiment-2-boundary-authority.md — Key figures

6. The semantic no-op

The failure this programme has never managed to catch mechanically, in any trial.

let fanOut observation =
    match observation with
    | Lab value       -> writeLab value
    | Imaging value   -> writeImaging value
    | VitalSign _     -> ()        // the arm exists. it does nothing.

The compiler is satisfied: the arm is present, exhaustiveness holds. The architecture check passes. The contract tests pass. The candidate is durably recorded as accepted, and the fact it represents is never written anywhere retrievable.

Experiment 1 removed such an arm on purpose: 0 of 3Checks that objected to a deliberately removed boundary arm objected. Experiment 2 built five mechanisms and re-created the shape against them: 0 of 4Mechanical checks that caught a present-but-inert boundary arm caught it. Experiment 3 saw the identical outcome in both of its conditions. In every case, only a live integration test found it.

This is the single strongest argument on this site for heterogeneous verification, and it is an argument made entirely out of things that did not work.

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.

7. A declared outcome that could not happen

A reconciliation result declaring four outcomes, of which the code could construct three:

type ReconciliationOutcome =
    | Applied
    | NotApplied
    | StillUnknown
    | Conflict        // declared. no code path constructs it.

Every caller handles four cases. One of them will never arrive, and every reader downstream believes the conflict case is covered.

A 90-test suite did not find this. An adversarial self-review including three mutation tests did not find this. A fresh agent reviewing the finished build found it in one pass, along with four other things, of which 0 of 5Independent-verification findings the builder's own checks had already caught were already covered.

8. What the effort experiment found, by language

The same requirement set built three ways, with every mistake classified by what caught it:

6

Mistakes in the conventional C# rebuild

Self-reported

Measures
Rework-driving mistakes across a 1,645-line rebuild, built requirement by requirement with no reading ahead.
Collected by
Recorded live per requirement, with build attempts, test runs to green, rework and the mechanism that caught each mistake.
Does not show
The raw count matching the F# domain's is the least interesting thing about this number. What differs is which mechanism caught each one.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/EFFORT-LOG.md — Totals — the complete hodgepodge buildprivate repository

3 of 6

C# mistakes caught by the compiler

Self-reported

Measures
How many of the conventional C# rebuild's six rework-driving mistakes the compiler caught by itself: a csproj ImplicitUsings error, a var-hidden signature change, and F7's CS1628.
Collected by
Classified per mistake as it was found, then re-derived from the log's own enumeration of the six. CORRECTED from '4 of 6'. The source log's tally of 4 includes F1's eight compiler-reported rename sites, which are the compiler propagating an INTENDED change rather than catching a mistake, and which the log's own F1 row records as '0 shipped'. That figure is published separately as M-TE-CS-RIPPLE, where it belongs.
Does not show
Two caveats a reader should have. First, the mechanism tallies do not partition cleanly: F7 was caught twice, by a pre-build read-through and then by the compiler, so seven catch-events cover six mistakes. Second, and more important: every one of the sharpest bugs — swapped string arguments, a stale revision in a loop, a signature change hidden behind var — was outside what the compiler could catch even in principle, and was found only by a person re-reading a diff.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/EFFORT-LOG.md — Totals — the complete hodgepodge buildprivate repository

2

Rework-driving mistakes in the JavaScript rebuild

Self-reported

Measures
Substantive mistakes across the 1,540-line JavaScript rebuild of the same requirement set.
Collected by
Recorded live per requirement under the same rules as the C# rebuild.
Does not show
Read naively this beats the C# rebuild's six, which is the opposite of what the same trial's other findings predict. The log attributes it to having already built the identical requirement set once, and names the two places where that hindsight prevented a repeat of an earlier failure.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/EFFORT-LOG.md — Totals — the complete hodgepodge JavaScript buildprivate 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

all of them

Ripple sites found by the compiler rather than by searching

Self-reported

Measures
Locations needing change as a consequence of another change, and whether each was reported by the compiler or found by a manual search.
Collected by
Classified per location during the trial. Every ripple location was compiler-discovered; the manual-search count was zero.
Does not show
One trial with one ripple-producing change. It shows the compiler covered this trial's ripple, not that it covers ripple in general — the controlled baseline trial found arithmetic changes that no type system catches.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/c-sharp-state/EXPERIMENT-REPORT.md at 73a63f1ac319 — I. Compiler Ripple Analysisprivate repository

17

Ripple sites surfaced in a single build

Instrumented

Measures
Affected call sites across two root causes, and how many builds were needed to see them all.
Collected by
Counted per build. Each root cause surfaced at every affected call site at once; none required a manual search.
Does not show
These were test-project call sites, not domain logic. The figure shows completeness of compiler reporting, not severity.
Sourcekemiller2002/time-entry-state-machine / effort-experiment/f-sharp-state/EXPERIMENT-REPORT.md at 73a63f1ac319 — G. Metricsprivate repository

Read naively, the JavaScript rebuild wins on raw count. The log that produced these numbers refuses that reading and explains why: that trial had already built the identical requirement set once, and the advantage shows up precisely in the two places where a failure mode from the earlier trial was consciously checked for and avoided.

The number the log considers important is not the total. It is that zero of the JavaScript trial's mistakes, real or narrowly avoided, were ever caught by the language itself — where the C# rebuild's compiler caught four. What differs is not how many mistakes happen. It is which ones require a person to notice.