2.3 The Governed Environment: Ex-Ante and Ex-Post
Everything so far assumes you know, in advance, what should be true about your software. If you do, the path is easy, of course: write it all into a specification up front and hold the agent to it. But real software engineering rarely works that way — you discover what you are building by building part of it. So a governed environment has two halves: what you can decide before you start, and what you can only learn along the way. This chapter is about both halves, and about the two forms every governance mechanism finally takes.
That an agentic team needs governance of its own is beginning to draw formal treatment. Recent academic work proposes a domain-specific language for defining and enforcing governance policies across mixed human-agent software projects 11. Adem Ait et al., “Towards Automated Governance: A DSL for Human-Agent Collaboration in Software Projects,” in “Proceedings of the 40th IEEE/ACM International Conference on Automated Software Engineering (ASE), New Ideas and Emerging Results Track,” special issue, Proceedings of the 40th IEEE/ACM International Conference on Automated Software Engineering (ASE), New Ideas and Emerging Results Track, 2025, https://arxiv.org/abs/2510.14465.. MAGE converges with that direction but works at a different grain: not a single policy language, but a repertoire of governance mechanisms drawn from a production case — the machinery this chapter and the companion catalogue lay out.
2.3.1 Ex-ante: everything you can decide up front
Some things you genuinely know from the beginning, and you should write every one of them down. This is specification-driven development, and where you can do it, you should. A coding style guide is the everyday example — Google has one, Airbnb has one — full of rules like "every function carries a comment" or "we never call exec outside this one approved place." Give the agent those rules, and then write deterministic checks for them. If a program's output has a required format, write the checker that confirms it — or, better, have the agent write the checker. Determinizing what you know up front gives you a much stronger starting point, and it costs you almost nothing, because the checks are cheap and the agent writes them.
2.3.2 Ex-post: everything you learn by building
But you will not know everything, and pretending otherwise is the mistake. You will discover that performance is a problem and you have no performance model. You will discover that a particular model version has a tic — every LLM's fondness for the em-dash is the running joke — and that the tics move when you upgrade. So you will build governance ex-post: after the fact, iteratively, strapping on new mechanisms as the failures reveal themselves and as the software's real properties emerge. You define what you can up front, and you stay willing to discover the rest. The rest is the mistakes you are making, the mistakes the model is making, the gap between what you thought the customer wanted and what they did, and the gap between how you thought the code would perform and how it did.
The honest version of the loop is less tidy than the ex-ante story makes it sound. You set up the governance you can imagine in advance, you launch the work, and then you watch it burn and then try to fix it. The failures you did not foresee are the ones that teach you which mechanism to build next. Ex-post governance is not a fallback for a weak plan; it is where most of the real mechanisms come from, because most of the real failures are the ones no specification predicted.
The engine of the whole discipline is what you do to hold a quality goal: you set up a mechanism that keeps it. This is the organizing move of the companion catalogue. You place some mechanisms up front, from what you know about the domain, and you add more in response to a failure seen twice — a mistake caught in yesterday's manual audit becomes today's automatic check, enforced on every agent thereafter instead of re-caught by inspection. That conversion runs the printer loop's own shape (introduced in Loops and Models), escalated: when the loop keeps hitting one wall, judgment turns the failure class into a durable mechanism (Figure 2.3-1).
None of this is new as an instinct. Manufacturing stops the line at a defect and reshapes the work so the defect cannot recur; resilience engineering treats an incident as a signal about the system, not a verdict on the operator 22. E. Hollnagel et al., Resilience Engineering: Concepts and Precepts (Ashgate, 2006).; site reliability practice turns each outage into a blameless postmortem whose action items become durable reliability work 33. B. Beyer et al., Site Reliability Engineering: How Google Runs Production Systems (O'Reilly Media, 2016).; Shingo built mistake-proofing into the fixture itself 44. Shigeo Shingo, Zero Quality Control: Source Inspection and the Poka-Yoke System, trans. Andrew P. Dillon (Productivity Press, 1986).. MAGE inherits that family and states its promotion rule for a fleet: an ex-post failure becomes an ex-ante control when judgment classifies the recurrence and encodes it in the environment. The changed ingredient is velocity: the fleet surfaces structural gaps fast enough that the environment can accumulate reliability one failure class at a time.
2.3.3 The controls accumulate
Run the promotion rule for a season and the environment fills with controls. The case project shows the shape. Figure 2.3-2 counts its two hardest control surfaces — project-specific lint files and gate scripts — at the same four windows the build passed through; Table 2.3-1 gives the numbers behind the lines.
| Window | lint files | gate scripts |
|---|---|---|
| prototype | 0 | 0 |
| mechanization | 336 | 20 |
| hardening | 595 | 76 |
| now | 747 | 102 |
The curve is the accumulation, not its cause. Those lint files carry 993 registered lint specs at the final window, and each spec is a policy the environment now enforces on every agent. What the count cannot separate is which controls a failure drove and which the domain suggested up front — the two modes interleave by design, and no commit trail cleanly splits them. But the discipline that converts a failure is itself documented and named. A paired fix-and-lint tag marks the commits that ship a code fix beside the check that forbids its recurrence, and it appears in 208 commits; 27 lints name a specific dated incident in their own text, spot-checked as genuine after-the-failure conversions. Read the curve as a documented, growing discipline, then — not a measured causal rate. For the data, see The Governed Environment: Ex-Ante and Ex-Post →
How large should the governed environment grow relative to the product? Conventional wisdom offers a rough rule — about one line of tests for every line of production. The timeline and the work measures the support ratio MAGE actually reaches against that yardstick.
Either way you arrive there, a mechanism takes one of two forms, and the difference between them is the difference between a firewall and a smoke detector.
2.3.4 Constraints and sensors
A mechanism is one of two moves — prevent the mistake, or catch it — and Figure 2.3-3 draws the split.
Before the two forms, the argument for reaching for a mechanism at all. Words alone do not hold. Tell the agent "make sure the briefs always follow this template" and it will say, "Sure, boss" — and then it will not reliably do it, not all the time, because it is a probability flip. A prompt raises the odds; it does not settle them. But you can determinize that. Instead of hoping, you check: before the agent launches, confirm every required part of the template is present, and refuse the launch when it is not. The soft instruction becomes a hard gate. That move — from a probability you nudge to a condition you enforce — is the reason the rest of this chapter exists, and it splits into the two forms below.
A sensor detects drift. It lets the mistake happen and catches it after the fact — and because it fires after, it fails the loop iteration: the agent has to run again to fix what the sensor caught. Your test suite in CI is a sensor, and so are your lints. It would be better if the model never wrote the bug; but if it does, the sensor catches it before the code ships. The cost of a sensor is iterations — detect, fail, re-iterate — and that cost is the reason you do not reach for one first.
A sensor is only as good as the signal it can read. Observability is the property that a running system exposes enough signal to explain what it did and to catch what went wrong. It is the wiring under every sensor: the event a gate fires on, the log a checker reads, the trace that turns "the build failed" into "the build failed here, for this reason." Build the observability first and the sensor has something to watch; skip it and it stares at a blank wall.
A constraint prevents drift. Where a sensor detects an instance of the mistake after the fact, a constraint makes the whole class impossible: it scopes the agent's action space within the iteration, so the wrong move is never available to pick. The cleanest example is types. Models are, by default, careless with types — and a compiler exists to confirm that functions are called with the right arguments. Suppose the agent has represented a state with bare strings. Because it is a language model, it will cheerfully reach for a synonym next time, and the synonym silently fails to match — and you only learn that an iteration later, when a sensor, the test suite, crashes. Tell it to use an enumeration instead, and the whole failure mode evaporates: it can no longer invent an unlisted value, and if it tries, the compiler rejects it on the spot. Choosing the enum over the string forbids the bug rather than watching for it, and because the wrong value can never be picked, no iteration is spent catching it. This is why the catalogue leans so hard on structured models and closed enumerations over free-form strings: a constraint that removes a mistake costs no iteration, while a sensor that catches it costs at least one.
Learn more about this governance mechanism: closed enumerations over free-form strings.
A footnote on control engineering. Constraint and sensor are the working terms of control engineering. A governed plant — a reactor, an autopilot — carries constraints on the inputs and states it may reach, and sensors on the outputs it produces, so the controller can read the error and correct the next cycle. I kept the terms because the parallel is exact. A fleet of probabilistic machines is a plant you cannot run open-loop; the governed environment is the loop you close around it. Constraints scope the action space, sensors read the output and fail the iteration, and the next iteration corrects. Engineers have run unruly physical processes this way for a century. Governing a fleet inherits the discipline along with the words.
Learn more: Nancy Leveson's Engineering a Safer World 55. Nancy G. Leveson, Engineering a Safer World: Systems Thinking Applied to Safety (MIT Press, 2011). applies the same systems view to safety engineering.
Two axes cross here, and it pays to hold them apart. A mechanism has a form — soft, it aims the agent, or hard, it holds regardless — and a move — a constraint, it prevents, or a sensor, it detects. The two are independent: a constraint can be soft (a structured model that aims the agent's reasoning) or hard (an enum the compiler enforces), and a sensor can be soft (a convention that reminds) or hard (a lint that blocks). Constraint-versus-sensor is what the mechanism does; soft-versus-hard is how firmly it does it.
Most real mechanisms are a package across both axes. A structured model is a soft constraint on the agent's reasoning — it aims the agent at the right shape without forcing it — and it ships with hard sensors, the lints and drift-parity gates that catch what the soft constraint only aims at. The definition-of-done review is the same shape: a runbook that constrains the steps, wrapped in sensors that flag a drifted one. So name the package, and tag its primary move rather than forcing it into one bin: prefer a constraint where you can build one, and add a sensor for the drift you cannot scope away. ("Architecture" is the design activity that builds constraints — not a third kind of thing.)
Seen from the outside, this is what a purely organizational answer leaves on the table. Faced with an unreliable worker, the instinct is to wrap it in process: a review, an approval, an evidence trail, a sign-off before the work counts. Every one of those is a sensor. Each lets the mistake happen and catches it after the fact: ex-post, an iteration late, an inspection of output the agent has already produced. A discipline built only of sensors can raise the odds and shrink the blast radius, and yet it never removes a failure class, because it watches the action space instead of scoping it. The constraint is the move that answer does not have: it works ex-ante, inside the iteration, so the wrong move is never available to pick. That is the difference between supplying reliability by construction and inspecting for it after the fact.
A footnote on the factory floor. The Engineer's Seat introduced Toyota's names for these two moves: the constraint is poka-yoke, and the sensor's fail-the-iteration reflex is jidoka. The lesson Toyota drew is the one this section just argued — inspection at the end of the line cannot build quality in. A fleet of agents is a production line for code, and it relearns the same economics.
Four classes, one bounded term
One boundary before moving on, because without it the word swells. Prompts, documents, lints, tests, metrics, hooks, models — everything in the environment starts to look like "a governance mechanism," and a term that covers everything governs nothing. Bound it:
Governance mechanism. A repeatable environmental structure that encodes an engineering policy and either constrains an action, detects a violation, requires evidence, or controls admission.
The clause list yields four classes: prevention, detection, evidence, admission. The first two are the constraint and the sensor you just met — the catalogue's move axis tags them, with package naming a bundle of both. The other two sit at the loop's far edge. An evidence mechanism demands the change carry its proof: a provenance stamp, a re-derived test result, a completion re-checked rather than self-reported. An admission mechanism decides whether the result may advance at all — the admission rule of the engineered loop (1.3), holding the last door.
The evidence and admission classes compose into what is worth naming the evidence staircase: cheap checks run early and bind their result to an exact tree, so a later, more expensive stage can check that binding rather than trust a report; and the definition of done recomputes the full evidence at close instead of reading a marker. Cheap evidence early, full re-derivation late, never a trusted self-report — the same staged-admission-plus-re-derived-completion pair the catalogue lists as a composition, read here as how a loop earns the right to advance.
The definition also settles a boundary this book leans on: a model is not a governance mechanism until something reads or enforces it. A structured model on disk aims nobody. The lint that reads it, the gate that checks the code against it, the generator that derives from it — those are the mechanisms. The model supplies the policy; the mechanism supplies the holding.
What it adds up to
Step back and this is what you are really doing: describing policies for how the engineering work should proceed, and letting those policies produce a governed engineering environment — the rules of the road the agents operate within. That combination — determinize what you can, then convert every recurring surprise into a constraint or a sensor — is the governed engineering environment.
2.3.5 The residual: goals no mechanism reaches
That closing line reads as if it settles everything. It does not: some goals split into neither. No cheap sensor can see the failure and no constraint can scope it away, because the failure is an absence nobody specified, and you cannot watch for the violation of a rule no one wrote or forbid an action the design never mentioned.
Security remediation is the clean case. A missing authorization check has no failing test — by definition. If a test caught it, the check was specified; if it was specified, it would not be missing. The gap is invisible because nothing ever named it. So the goal stays a human job: someone has to look at the system and know the check should be there. Call this the residual: the third outcome beside prevent and detect, the goals no mechanism reaches. Which of your goals land in it sets your real throughput ceiling. The mechanized goals run at fleet speed; the residual runs at yours — and it is the residual, not the size of the catalogue, that bounds how fast the whole system can go.
This is not the soft end of the soft-versus-hard axis you just met. A soft mechanism — a structured model that aims the agent, a convention that reminds — is still a mechanism: a named artifact that raises the odds and that you can point to. The residual has none. There is nothing to name, nothing to tag as a constraint or a sensor, nothing to add to the census. It is the complement of the two moves, not a third value on the axis.
Naming the residual costs the method nothing; a method that claims to mechanize everything is the one to distrust. The residual is the honest edge that makes the mechanized core credible — it says plainly what the catalogue does not cover, and that admission is what lets you trust the coverage it does claim.
Nor is the residual a fixed wall. You can sometimes pull a goal out of it by authoring the missing spec. The same absence that defeats a sensor defeats a derived model: a model read off the code records the missing check as correctly absent, and the drift gate agrees with the bug — a mirror cannot see what was never specified, which is the residual restated for models (2.2). And a journey test that only asserts "the flow ran" greens while the user's task is broken, until a human authors the terminal task-closure assertion that says what done means — turning an un-sensable goal into a checkable post-condition (3.6). Both are the residual met again: once as a model that cannot reflect an unwritten intent, once as a spec that authorship supplies. What that human residual becomes when the model, not the code, is the thing you author — the enduring job that moves one level up — is the subject of the closing chapter (6.0).
Works Cited
- Ait, Adem, Gwendal Jouneaux, Javier Luis Cánovas Izquierdo, and Jordi Cabot. “Towards Automated Governance: A DSL for Human-Agent Collaboration in Software Projects.” In “Proceedings of the 40th IEEE/ACM International Conference on Automated Software Engineering (ASE), New Ideas and Emerging Results Track.” Special issue, Proceedings of the 40th IEEE/ACM International Conference on Automated Software Engineering (ASE), New Ideas and Emerging Results Track, 2025. https://arxiv.org/abs/2510.14465.
- E. Hollnagel, D. D. Woods, N. Leveson. Resilience Engineering: Concepts and Precepts. Ashgate, 2006.
- B. Beyer, C. Jones, J. Petoff, N. R. Murphy. Site Reliability Engineering: How Google Runs Production Systems. O'Reilly Media, 2016.
- Shingo, Shigeo. Zero Quality Control: Source Inspection and the Poka-Yoke System. Translated by Andrew P. Dillon. Productivity Press, 1986.
- Leveson, Nancy G. Engineering a Safer World: Systems Thinking Applied to Safety. MIT Press, 2011.