The watchdog that died quietly, and took the evidence with it

2–3 minutes
measured on my own machine
A toppled faceted guard lying at the head of a long dark corridor of nine empty bays, the small amber message it was carrying lying unopened beside it.

For nine nights my LinkedIn agent reported nothing. Not an error — nothing. The loop started at 01:20, ran, and left a log that said it had died. Eight nights out of eight, at the same place: its own identity gate.

The gate exists for a good reason. My personal LinkedIn profile is not allowed to carry product talk — I have a day job, and colleagues read that profile. So a guard scans everything the agent produces and kills the run if it finds a brand name where a brand name must not be.

Here is what actually happened. The agent could not post, because a file it needed was missing. Being a well-behaved agent, it wrote a report explaining why. And in that report, it quoted the blocklist it had just failed against:

… every link to georgsinger.ai / seitenhebel.de / emailmanager.ai is removed …

The guard read the report, found three brand names, and killed the run.

The part that cost the nine nights

Killing the run was not the expensive bit. The expensive bit is that the run was carrying a notification naming the real cause — the missing file. That notification never left. So every morning the system looked quiet, and quiet looks a lot like fine.

A watchdog that reports only when something changes state can die without anyone noticing, because a dead watchdog and a vigilant one produce exactly the same output: silence. This one went further. It did not just fail to report — it actively destroyed the report that would have exposed it.

A guard that shoots the messenger carrying its own finding does not merely fail. It conceals its own failure.

It was the second time

That is the detail I find hardest to write down. Three weeks earlier, the same class of bug had already happened in the same file, in a different function. It was fixed at the place it was found. The general shape of it — a check that cannot distinguish a violation from a report about a violation — was not.

My own rule says: if the same case appears a second time, the first fix was cosmetic. I wrote that rule. I then broke it, in the file where the rule is quoted in a comment.

What the fix actually is

Not a longer allowlist. The gate now distinguishes between the text an agent wants to publish and the text it writes about its own run. A report is not a post. Only the publishable section is scanned; the reasoning around it is not.

That sounds obvious written down. It was not obvious while the system was quietly doing nothing, because there was no symptom to be obvious about.

The cheap check that would have caught it

One line, and I did not have it: a loop that is switched on and produces no artefact for two consecutive nights should say so out loud. Not fail — say so. The absence of output is a signal, and it was the only signal available here.

It now writes that line. Last night it read: not due, already ran successfully on Saturday. Which is the same silence as before, except now I know which kind of silence it is.

Georg Singer

Georg Singer

I automate my own projects in public and write down what each one cost. Physics degree, doctorate in computer science, nine systems in production on hardware I own, all of it built in my own time.

More from the log