2.6 When Guardrails Collide

The stack gives you four layers to steer at, and a governed fleet fills them: a hook at the harness that fires at turn-end, a lint at the application that gates a commit, a skill that aims a task, a mediator that rations a lock. Pick a layer, inject a constraint — and the constraints accumulate. Each earns its place alone, of course. But the more mechanisms you install, the more pairs of them touch the same thing, and together they form a system — and a system of controls has the one failure a list of controls cannot show: two of them making incompatible demands on the same thing at the same moment.

Two collisions from the case study make it concrete. In the first, one path required a commit to take a squashed shape while a separate check flagged out-of-brief changes on that same commit-set — two controls, one resource, contradictory demands, caught only when a real commit tripped both. In the second, two hooks fired on the same turn-end with no order declared between them, each able to block, resolved by hoping they composed. Neither collision lives in any one control's code. Each lives in the space between two controls, and that space was drawn nowhere — until Figure 2.6-1 draws it: two correct controls, one shared resource, a contradiction on the edge between them.

The conflict is the edge — a collision drawn nowhere until the graph draws it Two control nodes — Control A, which requires a squashed commit, and Control B, which flags out-of-brief changes — each correct when read alone. Both point by a solid arrow to one shared resource, the commit-set, that they act on. A dotted edge runs directly between the two controls, labelled as the contradiction: the conflict is that edge, present in neither node’s own code, arising because the two make incompatible demands on the one resource they share. Control A requires a squashed commit ✓ Control B flags out-of-brief changes ✓ shared resource: the one commit-set acts on acts on the conflict is this edge: in neither node’s code
Figure 2.6-1. The Conflict Is the Edge. Read Control A alone and it is correct; read Control B alone and it is correct. What they demand of the one resource they share collides — and that collision is drawn nowhere until the graph draws it.

2.6.1 Drawing what lies between the controls

The Governance Graph draws it. The nodes are the mechanisms — each tagged with the event it fires on and the resources it reads, writes, or locks. The edges are the conflicts, in a closed four-value taxonomy: contradiction (two demand incompatible shapes of one resource), contention (two lock one resource, risking a deadlock cycle), ordering (one writes what the other reads on the same slot, with no guaranteed order), and soft-versus-hard (a soft aim overridden by a hard block on the same slot). The join key is the shared resource. Two controls that never call each other still collide if they both touch the turn-end slot, so the resource — not the call — is what makes them comparable. Type the turn-end slot and the context budget as resources too, and hook-pileup and injection-pressure fall under the same conflict machinery as a contended lock. One analysis covers all of it.

The shared resource is also what lets the graph reason across lifecycles. Most collisions are local — two controls in one lifecycle touching one nearby resource. But a hook that fires at turn-end and a check that fires at commit live in different lifecycles, and they still collide if they both reach for one typed resource. The resource is the only coupling surface between lifecycles: controls in different lifecycles that share no resource cannot conflict, which is what keeps the graph sparse. And this is the semantic gap again — the collision is a property of the interaction, invisible in either control's own code, legible only at the level where both are drawn. The graph lifts the check to that level.

Learn more about this governance mechanism: Governance Graph.

A catalogue lists the controls; it can't show which two will crash into each other. The graph draws exactly those crashes: which pairs collide, and over what. It is the edges a list of nodes omits — the static catalogue's dynamic dual. And the two halves of that answer split cleanly. Some edges are mechanically decidable: a same-slot pair with no declared order, a lock cycle. A lint settles those. Others need judgment: are two constraints on a commit-set truly incompatible, or do they compose? No lint decides that; a reader must. So each edge carries its nature, derived from its type, and the decidable edges route to a sensor while the semantic ones route to a human prompt. This is where the motivating commit-set collision was really lost — the machine could flag that two controls touched the commit-set, but only judgment could call the contradiction. The graph makes both the flag and the prompt land before the control ships rather than at the collision.

That is the operational payoff. A governed environment is not just a pile of running mechanisms; it is a claim that those mechanisms compose. The claim was implicit, checked by collision. The graph makes it explicit and checkable: ask what fires on this event, what touches this resource, is this new control consistent with the ones already wired — and get an answer at authoring time. The fleet stops merely running its guardrails and starts modeling how they interact.

2.6.2 The other question a list can't answer

The graph settled one question a flat list could not: which two controls collide. A second question hides in the same blind spot. A list names every control the fleet installed, and the graph draws every pair that can crash — but neither says which target has nothing watching it at all. A governed estate grows toward the last painful failure, piling controls onto the target that just hurt while another accretes nothing, and that imbalance is a property of the whole set, invisible in any single control's code.

So the same control node-set carries a third view. The list is the controls that exist; the interaction graph is how two of them collide; the coverage census is how many watch each governance target, and which target has none. Classify every control by the target it guards, roll the set up per target, and a target with zero controls — or with only soft aims and no hard hold — becomes a first-class finding. The empty cell is not an absence nobody noticed. It is the estate's own blind spot, named, and pointing at where the next control should go.

This is a model whose instances are the controls themselves, keyed by target — a metamodel, in the layering the model zoo names M0 through M3, one level up from the models that govern the product. And it turns the book's own method on the governance system: the governance-conversion loop turns each recurring failure into a control; the census asks whether the portfolio that results is balanced across everything that needs governing. Governance audits governance. Run first on the real fleet, it read one target fully populated and two at zero — two of three complementary targets entirely un-watched, invisible until the roll-up made the gap queryable.

Learn more about this governance mechanism: control-coverage census.

2.6.3 Growing controls, and auditing the growth

The census has a counterpart, and the two are true opposites over one graph. The fleet grows its controls the reactive way this book argues for: let velocity expose a failure, convert each recurring one into a durable guardrail. That reflex extends the graph — toward the targets that already failed. A target that has never bitten draws no new control, so the reactive discipline, left to itself, leaves whole targets structurally un-watched. It is a feed-back loop with a systematic blind spot.

The census is the proactive audit that catches exactly that. One mechanism supplies controls, reactively, failure by failure; the other measures the supply, proactively, target by target, and names the target the reflex never reached. Soft-reactive-extends on the one side, hard-deterministic-measures on the other: the reactive extender grows the estate, the proactive census keeps the growth balanced across every target rather than only the ones that hurt.

And the census holds itself equal to the territory by the same discipline it enforces on everything else. Each control's target is derived from its code anchor, never hand-declared, so the map cannot drift from the controls it counts. A control the rule cannot place fails loud rather than dropping into a silent default bucket that would mis-credit the coverage. The roll-up never blocks a commit — it aims the next control, it does not gate — yet the honesty backstop beneath it is hard. The census even files its own anchor-drift guard, so the control set censuses the very governor that measures it.

2.6.4 When the hooks aren't yours

Every mechanism so far was one you wrote. But some hooks arrive from outside — a plugin registers one, a teammate adds a personal one, and, plausibly soon, a regulator or a model vendor mandates one: run your agents with these prescribed governance hooks, or you are out of compliance. The graph extends to these without changing shape.

An outside hook enters as a node with its firing event known (you can read when it fires from its registration) but its resource footprint unknown. Unknown is not empty; empty would mean "verified to touch nothing," and you have verified no such thing. So it sits on a possible-conflict edge against every mechanism sharing its firing slot, until someone analyzes it into a known node or flags it un-analyzable. That conservative default, it might collide with everything on its slot, is the honest reading of a black box, and it creates the right pressure: a mandated hook you have not reconciled shows up as unresolved conflict rather than as silent trust.

That makes the graph an instrument for composing governance you did not author. Satisfying one regulator is checking that your mechanisms plus theirs leave no unresolved conflict. Satisfying several at once is the same check over the union: the composition is compliant exactly when the merged graph carries no contradiction, and a contradiction between one regulator's mandated hook and another's is a compliance impossibility, surfaced at authoring time instead of at audit. Because the graph types soft-versus-hard, it can settle the property a mandate cares about most: that a required hard block is never quietly overridden by one of your own soft aims on the same slot. Your own guardrails were the first use; governance handed to you (by a vendor, a regulator, a standard) is the same graph with more nodes, and "do I satisfy all of them at once?" becomes a question the model answers.

2.6.5 Keeping the model honest

Two disciplines keep the model honest, and both are the book's. Anchor each node to the code that implements its control by symbol, never by line, so a drift lint re-resolves the anchor on every build and a control wired but unmodeled reddens the gate: the map stays equal to the territory, or the graph lies about which collisions are covered. And keep the model descriptive — it draws the controls that exist and checks proposed ones on request; it does not invent conflict-lints for collisions that have never happened. A governance graph is itself a governance mechanism, and the failure mode of governance is a tower nobody wants. This one confines itself to the collisions that actually happen.

Learn more about this governance mechanism: symbol-anchored traceability graph.

This Part built the governed environment whole: the four layers you reach into, the soft aims and hard blocks that fill them, the metrics and lifecycles that run it, and the graph that keeps the guardrails from colliding. Every one of those checks the code against something it assumes already sits there — a schema, an invariant, a map of the controls. The environment enforces, but it does not supply what it enforces against. That is the model, and the next Part opens the zoo of them.

© James C. Davis, 2026–present