Every Automation Checks the Flag

The help text has said the same thing since May: pause: stop all automations (the global lever). The decision record behind it puts the promise in five words: every automation checks the flag. Yesterday I counted eleven that did not, and one of them was the job that publishes this page.

A file that means stop

The lever is deliberately dumb. aiops pause writes one file and aiops resume deletes it. A scheduled routine about to change something looks for that file first, and if it is there, prints [paused] and exits. No service to call, nothing that can be down at the moment I need it.

The weak word in that design is “looks”. The file does nothing by itself. Every routine has to ask, and asking is a line of code that whoever writes the routine has to remember.

The first gap

In early September a review by a second model pointed out that the flag had only a TypeScript reader. My older automations are plain JavaScript modules that could not import it, so none of them had ever checked. Until then, aiops pause had been stopping the TypeScript half of the workspace while the half that restarts services and commits to repositories kept going.

The fix was a small JavaScript reader for the same file, with a comment at the top I wrote with some satisfaction:

A lever with a silent exemption is not a lever.

After that I believed the lever was whole. The comment said so.

The second gap

Five weeks later the same reviewer flagged two more. My login watcher, which can stop sessions and send alerts, had no pause check at all. The nightly verification sweep had one, but it read a different file: the fleet’s pause, which stops coding agents from being dispatched and nothing else. It also read it after its first write, logging repairs to its journal before asking whether it was allowed to.

Two in one review is a pattern, so I went through every scheduled entry point and found nine more. A context tender that rewrites docs and pushes them to every repository. A hygiene job that quarantines files. Two that restart services. A watcher that files questions for me. A syncer that pushes. And three that dispatch agents, this site’s daily publisher among them, all through a dispatcher that checks only the fleet’s flag.

There are three pause files on my system: the global one, the fleet’s, and the agent watchdog’s. Each routine honored whichever one its author had in mind the day it was written. Nobody ever decided that the sweep should ignore the global lever. Whoever wrote it was thinking about the fleet.

What has to keep running

Adding eleven checks took an afternoon. The harder part was the list of things that must not stop.

The dead-man switch stays exempt: if I have typed nothing for seven days it pauses the fleet, and pausing it would disarm a pause. Backups stay exempt, because a pause usually means an incident, and a recovery point is what an incident needs most. Read-only reporters stay exempt, and every routine’s dry run still runs, since a report acts on nothing. Those exemptions now sit at the top of the reader, each with its reason. That list is the real design of the lever. The flag was always the easy part.

Then I set the flag and ran them by hand. Eight printed [paused] and exited clean, the dry runs reported as before, and I lifted it.

The one that cannot hear it

The fleet’s own code (the keepers, the dispatcher, the spawner) still reads only the fleet’s flag. It cannot learn the global one yet, because that directory is locked against edits by agents, under a guard I put there on purpose, and the agent doing this work is one. Changing it is a pack I apply by hand.

So today aiops pause stops every scheduled routine that acts, except the fleet of coding agents, which is the thing I most often reach for it to stop. That one has its own button on the dashboard. The help text still says stop all automations, and the next routine I write will start out the way all eleven did, never asking.


← all writing