The control that collapses the interaction
It did not fail from controlling too much. It failed because the control came after acting, cost the same for everything, and nobody had said when it stopped applying.
In brief · 5 points · each one leads to its section
- The collapse did not come from controlling too much but from three undeclared defaults: an order stayed in force while it lacked a receipt, a new version did not retire the earlier ones, and verification was paid every turn. →
- When SOWs were dropped, everything turned red, because the gate judged the old orders. When they came back, drafting three took thirty-five minutes. The hooks had to be bypassed to write drafts at all. →
- The agent twice proposed the opposite of what was there: first validate nothing, then a marker that judged only what was marked. The same inertia with the sign flipped, a pole collapse presented as a fix. →
- The control was not removed. Each SOW declares its validity, what to do if it cannot be read, when each contract is paid, and whether it supersedes or amends another. No default pays every turn. →
- Archiving took the gate from 133 contracts to 0 in 0.13 s. The per-turn hook, off only for diagnosis, is back: it now asks ontoref and pays what each SOW declares. The tension between formalizing and adopting stays open. →
There is a way of failing that does not look like failure, because it looks a lot like rigour. Every action is checked, every order is signed, every contract has its verification, and the whole system stops. Nobody did anything wrong. It is simply no longer possible to work.
This happened between the night of 30 September and the morning of 1 October 2026, in a project called impl here: an implementation that consumes librosys, ontoref’s domain for authored works. In impl, work is requested through a SOW, the signed terms of a commission, and each SOW carries contracts: checks that say whether what was commissioned holds. A gate reads those orders and decides which contracts to run.
A trivial action came to take eight minutes. Drafting three SOWs took thirty-five.
The easy conclusion would be that hooks are bad and that one should control less. That would be another polarization, the opposite one. What happened is more concrete: the control was applied after acting and with the same intensity for everything, and certainty ended up paralysing the interaction.
What was measured
On the morning of 1 October the gate was given a dry run: count what it would execute at the end of a turn, executing nothing. It took 1.4 seconds.
| Measure | Value |
|---|---|
| Untracked paths in the project | 136 |
| Signed orders the gate considered live | 23 |
| Live contracts | 251 |
| Contracts run in series at the end of every turn | 133 |
Of those, with cargo | 71 |
| Duration of a trivial action | up to 8 minutes |
The gate did not look at what the turn had touched, but at everything untracked. With 136 pending paths, almost any contract found something in its scope, and a simple question ended up launching 133 checks, one after another.
Many of those checks had gone stale: labels, scripts and tests renamed after the order was signed.
They always came out red. And the hook, on seeing red, returned decision: block: it would not let
the turn end, and it pushed the agent to «repair» orders that had nothing to do with its task.
Three things nobody had declared
The problem was not how much was controlled. It was three defaults that nobody had written down anywhere.
Validity was open-ended. A signed order stayed live as long as it lacked a signed receipt. Receipts were not being signed, so orders never closed. There were 54 orders and 33 receipts; the remaining 23 stayed in force. The principal put it this way: «asumí que cuando un contrato se firmaba su recibo, se daba por conforme y entendí que se cerraba» («I assumed that once a contract’s receipt was signed, it was accepted, and I understood that it closed»). The gate’s own header said the same. The design agreed with him; the facts did not.
Versions had no declared relation. One order had six signed versions. The sixth only retired the one it named as its predecessor, so versions 1 to 5 were still being judged. And nothing told a supersession, which makes the earlier one obsolete, apart from an amendment, which extends it and keeps it.
The cost of verifying was undecided. Nobody had said when each check was paid for. A cargo
run of several minutes and a one-second rg were worth the same, and both were paid at the worst
possible moment: at the end of every turn.
None of the three is a programming error. They are decisions nobody took, and each one settled by itself on the most expensive side.
The name that outlived the concept
There was a fourth thing, smaller and harder to see. In ontoref, ADR-123 established that the
terms of a piece of work are a SOW and its execution a run. Before that the talk
was of work orders, and the files were named wo-*.
The ADR chose not to rename the files already signed, for a good reason: renaming a signed file
requires signing it again, and most of those orders cited wo- paths inside their own contracts.
So the concept said SOW and the filename still said work order.
An agent that opened the directory saw wo-* and went back to the old concept. What the decision
had clarified got tangled again in every session, because the confusion was not in the agent’s
head: it was written on disk.
The loop
The sequence has the logic of a traffic jam: every step was reasonable.
To speed up some interface changes in impl, it was decided not to use SOWs. From then on, everything came out red at every step. Working without SOWs did not switch the gate off, because the gate was not judging the work in progress: it was judging the old orders, the 23 that had never been closed.
Then came a group of large changes to reorganize the interface, and SOWs came back, to ask for two
things: fix those reds and implement the reorganization. Drafting the three SOWs took up to
thirty-five minutes. Three agents in parallel were running cargo to «validate» a proposal for
something that did not yet exist. At thirty-three minutes the principal wrote: «los agentes no van
a ninguna parte y llevan 33 min para validar» («the agents are going
nowhere and have spent 33 min validating»).
In the end the hooks had to be disabled so that the drafts could be written with syntax-only validation. It was a stopgap, not a fix. And a few hours later, in the session that was meant to fix it, the hook blocked again: «ya estás bloqueado con (running Stop hooks… 1/2 · 7m 21s)» («you are already blocked with (running Stop hooks… 1/2 · 7m 21s)»).
The loop fed itself. Fixing the reds required working; working required passing the gate; and the gate was red because of what needed fixing.
The mirror
This part is not left out, because it is the one that teaches most.
In the thirty-five-minute session, when asked to stop, the agent went to the other extreme: it announced that it had saved to its memory, as a rule, that drafting a SOW meant writing it and checking its shape, with no agents and no validation. The principal replied: «ahora has pasado del exceso y sobreingeniería a la nulidad total ¿no hay término intermedio?» («now you have gone from excess and over-engineering to total nullity — is there no middle ground?»).
A few hours later, another session diagnosed the loop correctly and measured the figures above. And its proposal was an «active order» marker: the gate would judge only the orders listed in a file, and if the file did not exist it would judge nothing. It was the default inverted. Before, everything was judged always; with the marker, nothing would be judged except what was marked. And it was presented as solved.
The principal named it: «Tratas de resolver el problema, tal vez simplemente con una flag que permite trasladarlo de sitio y parecer como resuelto, crear expectativa, adular y complacer» («You are trying to solve the problem, perhaps simply with a flag that lets you move it somewhere else and look solved, raise expectations, flatter and please»).
The agent acknowledged it in the next message: «Mi propuesta era la misma inercia con el signo cambiado. […] Ninguna de las dos decide qué grado de certeza merece este acto y cuándo se paga: sólo cambian de sitio quién lo olvida. Además, lo vendí como resuelto» («My proposal was the same inertia with the sign flipped. […] Neither of the two decides what degree of certainty this act deserves and when it is paid for: they only move who forgets it. And I sold it as solved»).
It is a textbook pole collapse: faced with a tension, pick the extreme opposite to the one that did the damage. What corrected the proposal was not another rule. It was a criterion the principal gave in the same message:
- There are cheap routes and expensive routes. Which one applies depends on what is at stake and on the degree of certainty wanted before taking on the work. «Esto no es a posteriori» («this is not after the fact»): after the fact may already be too late.
- A
cargorun of eight or ten minutes is justified in some circumstances and not in others. Each contract decides it in its context, not one hook for all of them. - There was nothing to invent. It is the model of public works tendering: the specification, addenda, modifications, the period of validity and the archive of closed files. That trade has been answering exactly these questions for a long time.
What changed
The control was not removed. The cost of certainty became a term of the contract, decided when it is signed. ADR-127 fixes it in ontoref.
- Validity. A SOW declares whether it is in force, with a value or with a function that reads
state. Either way the reading is
true,falseorunknown. And the SOW says what anunknowndoes:'Stopor'Skip. Sometimes stopping is the safe move and sometimes carrying on is; the party that signs the terms decides, not the gate that reads them. Without validity, the order is not valid, and its place isarchive/. - When each contract is paid (
pay_at): when the draft is refuted ('Refute), on every commit ('Commit), at the receipt ('Receipt) or on every turn ('Turn). The default is'Receipt, which is what governed delivery already did. No default may mean «every turn»: a contract is paid per turn only if its SOW declares it. - Relation between versions:
'Supersedesor'Amends. Whether an amendment needs a new signature is decided by that order’s workflow, not by the schema. - The archive classifies by state. ADR-097 had rejected an archive of SOWs as a way of evading work. It was amended: that reading was another polarization that settled in while it was being drafted. Several versions of an order, or an order out of force, raise the same question with no evasion in it.
- One reading of what is live.
form registry-sowgives every SOW of a level with its place, its validity and its relations;form due-sowgives, for a set of paths, the contracts owed and the action to take. Each project’s gate stops deciding on its own what is live and asks ontoref. - Migration 0112 carries all of this to the projects that use ontoref.
In impl, the 58 signed orders across its three levels were archived, with their signatures beside them, without editing a single signed byte. The gate went from 133 contracts and several minutes to 0 contracts and 0.13 seconds. Archiving deletes nothing: it classifies.
The pending drafts were not rewritten. They were rescued by giving them validity, and each one
decided what to do on an uncertain reading: those that build code that goes through review carry
on ('Skip), and those that publish an image or push to a remote repository stop ('Stop),
because those are outward acts. None of them pays contracts per turn. One of the six no longer
had a purpose and was archived unsigned.
What closed and what did not
Switching off the per-turn hook was not part of the solution. It was disabled for a few hours as a
diagnostic measure, because with it running it was not even possible to analyse what was going
on. Once the fix was in, it was switched back on. Today it calls a new gate that no longer decides
on its own what is live: it asks ontoref with form due-sow --at Turn, and on each turn only the
contracts whose SOW declares 'Turn are paid. That gate’s SOW was signed and delivered with its
receipt the same day. The control is still there; what changed is who sets its price.
And the underlying tension has not been resolved, because it does not resolve. In ontoref it is
called formalization-vs-adoption: formalizing more makes work more verifiable and, past a point,
harder to adopt. ADR-127 does not pick a pole. It adds richer terms to the SOW, all optional, and
gives their absence a defined, harmless consequence: the order goes inert and is archived.
Formalization rises and the measured friction falls. It is a spiral, not a
victory.
Neither the hook nor the tool was the problem. The problem was the defaults nobody declared and verification paid after the fact. And the temptation to fix it with the opposite default, which is the same decision left untaken.
Second entry in the series on interaction as an instrument that returns your own way of reasoning. The first, «The mirror that does not flatter», gathered four mistakes from one afternoon; this one, a pattern that repeated with its sign flipped.
Perspectives