Putting AI on the Night Shift: Scheduled Tasks, Reporting Rules, and a Few Disciplines
The biggest change in how I use AI is not that my prompts got better. It is that I moved AI from “chatting with me during the day” to “working while I’m not there.”
My work machine almost never shuts down now. It runs a dozen-plus system scheduled tasks: before dawn it runs the full test suite against the main branch; early in the morning it checks whether dependencies or upstream APIs have changed, and when it finds something fixable it opens an isolated branch and lets an AI try to fix it; before work starts it rolls the whole night into a single digest. When I sit down in the morning, the first thing I do is read that digest — not open a chat box and ask “what should I do today?”
Here is what the whole setup looks like.
1. Scheduling the night shift
A night breaks into roughly four phases:
| Phase | Task | Output |
|---|---|---|
| Before dawn | Main-branch health check: pull the latest code, run the full suite | Red/green + failure logs |
| Early morning | Dependency security audit, upstream API contract drift | Read-only scans producing “repair candidates” |
| A bit later | Auto-repair (retried once on failure) | Isolated branch + draft PR, or marked blocked |
| Before work | Patrols for performance metrics, production errors, business metrics, repo state; then a roll-up | One digest, fed into the morning plan |
A few scheduling principles:
Separate scanning from fixing. Detection tasks are read-only and only write a “repair candidate” file. The repair task only accepts candidates that are complete, fresh, and based on the current main branch. A wrong detection costs at most a wrong report — it never breaks code on the side.
Stagger dependent tasks. Repair waits for detection; the roll-up waits for every patrol. The tasks have wake-to-run and missed-run catch-up enabled, ignore new triggers while an instance is running, and dedupe by date — a repeated trigger never repeats the work.
Every task started as a piece of manual work. After shipping new pages, I once ran a search-engine submission script by hand, then asked: “How do I make every new page get submitted automatically from now on?” That became a task: read update times from the sitemap, submit only pages changed since the last successful run, and let the next run cover any missed day. Drift checking was the same — at first it could only detect, not fix. I asked, “So you found it but didn’t open a fix PR?” That became auto-repair.
My rule now is simple: the second time I do something by hand, I ask whether it can go on the night shift.
2. Auto-repair: putting the night-shift agent in a cage
When an AI changes code unattended, the scariest outcome is not failing to fix the problem. It is “fixing” it by editing the tests, skipping cases, or loosening the gates until things turn green. So this part is designed entirely around distrust:
- The supervisor is not an AI. A plain script controls the flow; only the “change the code” step is handed to a command-line coding agent. When to run, which gates to apply, and whether to open a PR are all decided by deterministic code.
- The coder lives in a cage. Each issue gets a fresh worktree with a real dependency install. The coder has no network and no external tools, and never sees production configuration. Changing CI workflows, gate scripts, test configs, the database schema, or build scripts is explicitly forbidden.
- The gates are stricter than a human. Full local CI, a coverage floor on touched files, end-to-end tests (empty tests, skips, and retries that mask failures all count as failures), and a clean re-clone, install, and run. Finally, an independent read-only reviewer checks for new problems.
- Three rounds max. The code–test–review loop runs at most three times. If it still fails, the issue is marked blocked in the report instead of being forced through.
- The finish line is a draft PR. Only when everything passes does it push a fixed-name branch and open a draft PR. The script has no merge, no auto-merge, and no push to main. The merge button always stays with a human.
The night shift breaks too. Its first real run turned up four bugs in the supervisor itself: backslashes in Windows paths got swallowed inside an environment variable; a trim() on git status --porcelain output stripped the leading space of the first line and chopped the first letter off a filename; the network guard blocked the local pipe between parent and child processes as if it were the internet; and config quarantine also quarantined the example config. Another time the health check died at step one because a build-output path exceeded 260 characters and git clean failed.
So for the first week after adding a scheduled task, I read its report every morning, like onboarding a new hire. It is not something you can trust the moment it’s installed.
3. Three bookends a day: morning briefing, midday re-plan, evening log
Night-shift output needs a consumer. I cut the day into three fixed moves, each a skill:
- Morning: re-pull the task board live (never a stale snapshot), add the last dozen-or-so hours of commits, last night’s digest, and yesterday’s log, then rank today’s Top 5 and pick the single most important and hardest item to attack first.
- Midday: when code or task status has clearly changed, re-rank what’s left based on what actually got done.
- Evening: aggregate the day’s commits and PRs by my identity — several machines, several git emails — into a daily log.
The morning briefing and the evening log meet end to end: what closed yesterday becomes today’s candidates.
4. Controlling output: word limits and reporting rules
Looking through my recent chat history, the most common suffix I add is a word limit: “under 500 words,” “conclusion first, under 200 words,” “explain why in plain language, about 300 words.”
The reason is simple: agents default to elaborating, and the cost of a long answer falls on the reader, not on the agent. The first daily log I asked for came back several hundred words long, with a summary, details, and tomorrow’s plan. I sent it back with two lines: “Key points only, 200 words is the cap” and “No tomorrow’s plan.” Both rules went into the daily-log skill’s output format, and the problem never came back.
More important than length are reporting rules — telling it what not to report:
- Problems in third-party services get counts only, no causes or samples. I can’t fix them; the details only consume attention.
- Failures caused by the user’s own situation are not incidents and are excluded from patrol reports.
- The space goes to problems we can fix ourselves.
One more: every preview is a local file only. I look at it in a local browser or dev server, and nothing gets published as an online preview page.
5. Correct once, write a rule
The most valuable habit in this whole setup: every time I correct an agent, the correction becomes a rule with a reason attached.
The format is fixed: one line of fact, one line of Why, one line of How to apply. These rules live in a memory repo that syncs across machines, so any agent on any of my computers reads them when it starts.
A few examples:
- “Reply in Chinese throughout; never switch back to English mid-task.” After three corrections in one session, this was promoted from ordinary memory to a resident rule.
- “Public-facing copy states positively what something can do; no disclaimer-style negative sentences.”
- “Write each category of a spec as one paragraph, without numbering. State each requirement in exactly one place.”
Repeating a correction means the rule isn’t somewhere the agent is guaranteed to read. So whatever can become a machine gate shouldn’t live only in memory: the daily-log length went into the skill’s output format; “before merging, a second agent or an independent session must review the change” went into the pre-PR checklist. Memory relies on the agent’s diligence; gates don’t.
6. Handoff: running out of quota is not the end
Running out of quota mid-task, blowing the context window, or having to switch machines are all normal. My standing instruction: “Stop. Write a handoff prompt for another agent to continue, under 500 words.”
A good handoff answers only five things: what the goal is, what’s done, what’s left, which worktree and branch the code is in, and which traps were hit. Going over 500 words usually means it’s retelling the process instead of stating the state.
For longer tasks, state doesn’t live in the conversation — it lives in a tracker file in the repo: priority issues, unfinished tasks, uncommitted local changes, what’s been pushed, and what was explicitly cancelled. Conversations get compacted and cut off; files don’t.
I also often run two agents in parallel — one editing specs and copy, one writing code — and relay between them (“the agent next door is done”), each touching only its own part.
7. The human does three things: choose, look, merge
Put together, my daytime role collapses into three moves:
- Choose: pick today’s work from the morning briefing, and decide what not to do.
- Look: at results, not process. “Start the dev server for me to review.” “Just give me the links to the results.” I look at pages and artifacts, not at what the agent says it did.
- Merge: a local clean-directory CI run is the gate — temporary clone, lockfile install, full CI, without touching the dev directory I’m using. My rule is “once CI passes, open the PR, don’t wait”; the full end-to-end suite runs afterwards as the merge gate. I always click merge myself.
Closing
Looking back, the measure of using AI well is not how clever any one conversation was. It’s three things:
When you’re away, it’s working. When you’re there, it says only what matters. A mistake it made once, it doesn’t make twice.
The first comes from scheduled tasks and cages, the second from word limits and reporting rules, the third from turning every correction into a rule. None of it is hard. The hard part is doing it every time.