(Spine Ch. 49.)
“Early to bed and early to rise, makes a man healthy, wealthy and wise.” Benjamin Franklin, Poor Richard’s Almanack (1735)
Eleven agents, two workflows, one MinIO bucket, one database. By morning the evidence said eight tests were failing on clean main, three merges had blown up, and a toolbar badge still needed building. Three alarms, all ugly, all sitting there waiting with the coffee. I read them in order and started fixing the first one. The tell was small enough that I walked past it twice: the assertion values were not the same from one run to the next. Real regressions do not do that.
At 2am on 13 August 2026 a review agent on airank ran a SELECT against production and found that an offload job I had already approved would have overwritten 337,353 rows of archive pointers. I was asleep. I did not approve, review, or know about that catch until coffee. The machinery that found it was not the smart part of the stack. It was a query.
Bottom line: Unattended overnight work is not a model capability. It is a verification capability. The agent is allowed to run while you sleep exactly as far as something cheap and deterministic can tell you in the morning whether it worked, and not one inch further. If the only artifact waiting for you at 7am is a report of what the agent would do, you did not run an overnight job. You ran a very expensive brainstorm and paid for eight hours of GPU time to have it read nicely.
The thing that has to run all night is the check, not the model.
noclobber, in my case) refuses to
overwrite a log file, the merge commands never run, and the failure gets
reported to you as a git conflict. Jeremy Schoemaker, twenty-five years
of living in a shell, pwned by his own dotfiles.Among the longest-running Claude Code sessions, the 99.9th-percentile time the agent works before stopping nearly doubled in three months, from under 25 minutes to over 45 minutes (Anthropic, February 2026). Same paper: new users run full auto-approve in roughly 20% of sessions, experienced users in over 40%.
Forty-five minutes is not a night. The gap between “45 minutes at
p99.9” and “burned down ten jobs by morning” is filled by structure, not
a better model. Ralph Loop, which shipped in Anthropic’s official Claude
Code plugin marketplace as ralph-wiggum, is the crude
version: an autonomous loop that runs for hours unattended, marketed for
“night batch jobs that need to be finished in the morning” (Paddo.dev,
December 2025; Obvious Works, March 2026). Finished in the morning.
That’s what she said.
The loop is the easy half. The hard half is the sentence Zernie put better than I have managed to: an agent can run nearly unattended wherever you can check its output cheaply, deterministically, and a thousand times a night, and wherever you cannot, you are the bottleneck and a smarter model changes nothing about that (Zernie, July 2026).
So the pattern is four parts, and skipping any one of them turns your night into a report:
1. The goal has a shape, not a mood. Chapter 8’s ladder: PRD, milestones, phases, tasks, tests, prompts, build. By the time an overnight job starts, “every task passes its test” has to mean a specific command with a specific exit code. Anything I cannot phrase as a command is a daytime job.
2. The check is deterministic and it runs without
me. In commander-in-chief, the Godot project I have been
building since July 2023, the simulation core in src/sim/
uses fixed 16.16 integer math and a SimRng xoshiro128**
generator. A linter (tools/lint_sim.gd) fails the build if
anyone sneaks in a float, an engine RNG call, a Time.*
call, or scene-tree access. test_determinism.gd checks
FNV-1a golden checksums across runs, producing bit-identical state on
x86_64 and Apple Silicon. The formal name is deterministic simulation
testing (DBOS, July 2025; Zernie, July 2026).
3. Something external holds the state. Long-running agents have to solve persistence, recovery, and verification with a state layer that lives outside the model’s context window (Addy Osmani, Elevate, April 2026).
4. Remediation is bounded, investigation is not.
Autonomous investigation is reliable; autonomous remediation stays
bounded and supervised (DevSecOps.ae, August 2026). My night jobs get
free rein to read production, run tests, count artifacts, and write
code. They do not get an unbounded DROP, an unreviewed
schema migration, or a deploy to a customer-facing box without a
gate.
airank, the night of 13 August 2026. Two overnight runs.
The first was a council marathon: four implementations carried to completion before morning. Database optimization, toolbar readiness, webserver tuning, centralized logging. All four landed. Most were saved from their own authors by background machinery that had nothing to do with intelligence.
Save one is the 337,353 rows from the top of this chapter: a query, not a code review.
Save two: the nginx microcache config failed curl tests twice, once
on a hyphenated cookie name, once because it stripped
Set-Cookie unconditionally, which nginx -t
never flags and which breaks every login on the site. Fixed, it took the
site from 16.6 RPS at a p50 of 1.13 seconds to 1,873 RPS at a p50 of
10.3ms, a 113x speedup that would have shipped attached to a total login
outage.
Same night, second run. Eleven unattended jobs across two workflows, an overnight survey and a todo-cycle. Three times the evidence claimed something was broken. Three times the evidence was lying.
Eight tests “failing on clean main.” Eleven agents were running parallel suites against one shared MinIO bucket and one shared database, and the fixtures were colliding. I set that up myself, and it is Snakes on a Plane (2006): you know how it ends from the title, and I booked the flight anyway. Re-run solo on a quiet fleet, 17 of 17 pass.
“Three merge failures.” zsh’s noclobber flag refused to
overwrite a log file, so the merge commands never executed.
merge=1 was a shell error wearing a git conflict’s clothes.
The kill was counting: git log --oneline showed one merge
where four should be. Re-run with >|, four clean
merges.
Eleven jobs landed, three false alarms killed. Both nights I contributed nothing but the goal file and my continued unconsciousness.
Both nights went in the win column, which is the part I do not trust. Every overnight failure I have a record of got caught by a query, a curl, a test, or the morning log sweep, and I cannot show you the one that got past all four. That is not proof it never happened. A file drawer full of caught failures is exactly what a system with an uncaught one looks like, because the miss does not file a report. Read these two nights as the shape of the thing, not as a batting average.
The loud failure is the overnight run that crashes at 1am and leaves you a stack trace. Annoying, cheap, obvious.
The quiet failure:
The agent finishes, declares success, and the proof is a paragraph it wrote about itself.
“Implemented centralized logging. All changes verified.” No exit
code, no row count, no curl output, no git log --oneline
you can read in nine seconds. This is the Ch. 20 seam again: when done
is not a measurement, the most articulate artifact in the room wins by
default.
Second: your verification shares infrastructure with your work. Eleven agents writing to one bucket cost me a morning of fake test failures. A non-deterministic check is a coin flip with a log file.
Third: nothing watches the watcher. The scheduler died at logrotate time and no alarm fired, because the alarm was downstream of the scheduler. That is a smoke detector mounted inside the fire, and a dead cron produces silence that looks like a quiet night.
During the migration two days later, the scheduler’s cron line got commented out with a marker meaning temporarily, and temporarily ran from 13 to 15 August 2026. Thirteen scheduled tasks stopped. Every dashboard stayed green the whole time, because a scheduler is not a service, it is a pulse, and nothing was measuring the pulse.
The fix shipped on 15 August and it is eleven lines at the bottom of
routes/console.php: the schedule’s own last entry pings an
Uptime Kuma push monitor every minute, and the monitor,
airank-scheduler-alive, has a 180-second window, so three
missed beats page a phone. It reads the URL through
config() and not env(), because
env() returns null under config:cache and I
would have built a dead man’s switch that was itself dead. Eleven lines
buy back the two days I did not know I had lost.
Do
/goal, plus a workflow, plus “every task passes its test,”
plus “work autonomously, I have to sleep.” The fourth clause is only
safe because of the third.git log --oneline, a diff stat. Something a person can
check in under a minute.Don’t
merge=1 was zsh, not
git.Ch. 8 built the ladder that makes a /goal block
executable. Ch. 14 is the Ralph loop, and this chapter is that loop with
the lights off and no one to ask. Ch. 15 is why the plan is not the
work, the same argument moved eight hours later. Ch. 36 is the
verification layer this chapter leans on entirely: no cheap
deterministic check, no unattended night. Ch. 60 is where this scales
past one machine and one person’s sleep schedule.
Thesis is Jeremy’s: argument, not citation.
Verified:
ralph-wiggum) in Claude Code’s official
plugin marketplace. Paddo.dev, December 2025:
https://paddo.dev/blog/ralph-wiggum-autonomous-loops/Set-Cookie bugs caught by curl; nginx
microcache 16.6 RPS / p50 1.13s to 1,873 RPS / p50 10.3ms.
~/Projects/airank/blog/2026-08-13-three-saves-in-one-night.mdnoclobber masquerading as git merge conflicts.
~/Projects/airank/blog/2026-08-13-three-liars-in-one-night.mdSimRng xoshiro128**,
tools/lint_sim.gd, test_determinism.gd FNV-1a
checksums, bit-identical across x86_64 and Apple Silicon.
~/Projects/commander-in-chief/CONTRIBUTING.md/var/log, caught by the morning log sweep; already-shipped
toolbar badge requested by a four-hour-stale survey, closed as a
verified no-op. airank, 13 August 2026:
~/Projects/airank/blog/2026-08-13-three-saves-in-one-night.md~/Projects/airank/blog/2026-08-15-the-night-the-loop-ran.mdroutes/console.php pinging an Uptime Kuma push monitor
every minute, monitor airank-scheduler-alive with a
180-second window, URL read via
config('air.scheduler_kuma_push_url') because
env() is null under config:cache. airank
source: ~/Projects/airank/routes/console.php and
~/Projects/airank/config/air.phpWhat I could not verify:
~/Projects/airank/blog/,
10 to 19 August 2026: every incident on record was caught by a query, a
curl, a test, or the log sweep. The body says outright that an archive
of caught failures is not evidence there were no uncaught ones./goal text from the 13 August 2026 runs is
not preserved in ~/Projects/airank/.claude/worktrees/ or
.opencode/. The Do section gives the shape and labels it
memory.