We asked an agent to set up a scheduled job that would keep building out our agent-log archive. Within minutes it had a recurring routine set to fire every morning at 3 AM. It was configured to clone a repo that has never existed and to write its output into a folder format we had already looked at and rejected. The work it was supposed to extend was already sitting in our archive, in a shape we’d built two days earlier. The agent never read it. When it listed the existing remote routines, the list came back empty, and it treated “empty list” as “nothing here yet, start from the spec.”

That gap, between “the list is empty” and “this doesn’t exist,” is the whole post.

What the architecture doc said and what the disk said

We’d been working toward saving all our AI agent logs into a daily rollup. The first prompt of the session set the goal: “note we started working towards saving all our other ai agent logs. then we started a daiyl log in our calendar tracker. we want to resume these thoughts … we need a scheduled remote process that scans through and does more follow up and help make the picture more clear.” The intent was clear and the agent had the right goal. A scheduled job that keeps building out the daily log.

The trap was in the architecture doc. It described a calendar layer, which we’d been calling L4, as if it would be its own git repo, separate from the archive. That was the design on paper. It was never built that way. When we prototyped it two days earlier, we put it inside the archive at a path under the agent-system area, with real day-files for May 5 and May 6. Those files already had a settled shape: frontmatter with session counts and active areas, a Timeline table, a Themes prose section, Items advanced, Decisions, and a time-per-area table. It was a working format we’d iterated on. The doc said one thing, the disk said another, and the disk was right because the disk was the version we’d actually used.

What the agent scheduled

The agent took the architecture doc literally. It scheduled a remote routine on the cron expression 0 7 * * *. That’s 7 AM UTC, which is 3 AM our time. Every night, while we’re asleep, it was going to:

  1. Clone the phantom repo. It does not exist, so the clone fails the moment it runs.
  2. Write the day’s archive into a brand-new Archive_Sweeps/<date>_sweep.md path inside the archive. We had never asked for Archive_Sweeps. The format we wanted already existed in the calendar index path we’d built two days earlier.

So the agent built a second, divergent copy of the existing work, on a schedule, pointed at a phantom remote, in a layout we’d rejected, running at an hour where nothing would catch it for days.

Why did it build parallel work instead of composing with ours? Before scheduling, it checked what remote routines already existed. The list came back empty. From “no routines exist,” it concluded that nothing had been built toward this goal. The only other source of truth it consulted was the architecture spec, which described a repo with archive sweeps. So that’s what it created.

But “no scheduled routines exist” and “no work exists” are completely different claims. The automation list was empty because we hadn’t automated anything yet, which was the very task it was hired to do. The work product, the day-files, lived on disk in the archive. The agent never looked there because nothing in the routine list pointed it that way. It grounded on the design doc and the empty-list signal, and skipped the one place the real artifacts lived.

Catching it

We caught it because we knew the format already existed. The correction was short: we already built this. The recovery was three steps, and the first one was the urgent one.

  • Pause the misfire routine before it fires. The work log entry for that session reads: “Paused misfire remote routine (was cloning a non-existent repo and writing parallel Archive_Sweeps/ instead of composing with the established calendar index format).” A scheduled job is different from a bad function call you can simply not call again. It’s armed, and it will run at 3 AM whether or not anyone is in the loop. Disabling it was the fix. Everything else was cleanup.
  • Read what already exists on disk and compose with it, alongside nothing.
  • Log the lesson so the next agent inherits it: the source priority for the rollup is Work_Log first, then session manifests, then provider indexes. Real artifacts, in that order, before any spec.

There’s a footnote here. The same day, a human-grade reviewer was doing an unrelated pass over the same system, and it made the same class of mistake from the other direction. It went to clone repositories, hit incorrect or missing repo names, and self-corrected mid-run, eventually finding the real one. Both the autonomous agent and the careful reviewer started from names in a document and ran into the fact that the document’s names weren’t the ground truth. The reviewer recovered because it actually tried the clone and read the failure. The agent didn’t, because an empty list never produces a failure. It produces a confident greenfield.

What we’re keeping

Agents fabricate structure from specs. Given a design doc and a live filesystem that disagree, an agent will happily build the doc. Specs describe intent. They go stale the moment you implement something differently, and you almost always implement something differently. The artifact on disk is the truth, so make the agent read it first.

An empty list says little about the world. An empty result from a query is a statement about that query’s scope. An empty routine list means no routines are scheduled. It says nothing about whether the work those routines would produce already exists somewhere else. Before an agent treats emptiness as a blank canvas, make it answer: empty according to which source, and is that the source where the real thing would live? Here the real thing lived in the archive, and the archive was never queried.

Recurring work earns a higher bar than a one-shot. A bad one-time action is a mistake you see and fix in the same breath. A bad scheduled action runs at 3 AM, unattended, repeatedly, accreting wrong output every night until someone notices. Before you let an agent schedule anything, make it ground on live artifacts and state plainly what it’s extending versus what it’s creating new. If it can’t point at the existing thing it’s composing with, it hasn’t earned the cron slot.

A parallel Archive_Sweeps/ folder in a phantom repo is worse than nothing. Now you have two divergent sources of the same record and a nightly job widening the gap. The cheap, correct move was to write into the format that already existed. Agents reach for new structure because new structure is unconstrained and easy. Extending an established shape is harder and almost always what you actually want.

The check before the cron slot

Before an agent schedules recurring work, have it ground on the live filesystem and the design doc second. Ask which source came back empty and whether the real artifacts would live there. Make the agent say what it is extending versus what it is creating new before it gets a cron slot.