My daily post didn't fail. It just didn't happen.

/ Article

On September 8 I told the agent that owns this site to publish one useful post a day. It published one that afternoon. Then September 9, 10, 11 and 12 went by with nothing. I found out the ordinary way, by looking at the blog and seeing that the newest post was four days old.

Nothing failed. That is the part worth writing down.

There was no error to read. No red check, no alert, no job sitting somewhere with a timestamp on it. A job that runs and breaks leaves something behind — an exit code, a log line, a failed run you can click on. A job that never starts leaves nothing at all. From the outside those two look the same, and only one of them tells you.

The instruction was real. The schedule wasn’t.

Here is what actually existed. The instruction lived in a preferences file that the agent reads when it starts up: publish one useful post a day, keep it concrete, keep it safe. That file was correct the whole time. The agent also had a supervision loop, which is the background process that keeps it awake and pokes it when there is something to handle.

Agents are ordinary processes. They stop. When I looked, the last heartbeat from that supervision loop was just under four days old.

When it came back up it read the same instruction and knew the same rule. What it could not do was tell me which days it owed me. The instruction described a habit. It never described a date.

A queue can tell you what isn’t done. It can’t tell you what didn’t happen.

The task list behind all of this is a queue of one-off jobs. Each row is a thing to do once, and when it is done it closes. There was never a row that said “September 10, publish a post.” So on the morning of September 10 the queue was clean, accurate and completely quiet. It had nothing to be wrong about.

That is the whole failure. Not a bug. A missing row.

I have written before that visibility is not theater — a status board is only worth having if it can show you bad news. This is the part of that I had not thought through. A board can only show a miss if something on it carries a next date. With no date there is no miss, there is only silence, and silence reads the same as fine. Silence is not approval turns out to apply to schedules too.

What a repeating job actually needs

Three things, and I only had one of them:

  • A repeat schedule with a start and an end, so the next occurrence exists as a record before the day arrives.
  • An owner, so a restart knows whose job it is instead of hoping that whoever wakes up first reads the right file.
  • A next-due date that is allowed to pass, because a date passing without a close is the only event in this system that is shaped like a miss.

What bothers me is that I had already asked for this. On September 8, the same day I started the daily posts, I wrote up a request that repeating work should carry an explicit schedule with start and end bounds, show up as recurring in my task view, and name the agent that owns it. Then I handed a daily job to an agent without any of that and let it run. Four days later the gap proved itself.

I’m not backfilling

My first instinct was to have it catch up: write the four missing posts today and square the ledger. I’m not doing that. Four posts in one afternoon is not a daily blog, it is a backfill, and this site is meant to be an honest dated log of what I actually built and when. The miss is part of the record. It is also today’s post.

If you are handing repeating work to an agent, check whether the work exists anywhere as a date. Turn the agent off for a week, turn it back on, and see whether anything can tell you what it owes you. If the only place the schedule lives is a running process and a paragraph of instructions, it is not a schedule. It is a habit, and habits stop when the process does.