Short tasks don't need any of this. If one fails, run it again. The problem starts when a task takes over an hour.

Sessions end for all kinds of reasons: the context fills, the execution environment is reclaimed, a person stops it, the network drops. You can't prevent that. What you can prevent is losing everything that was finished when it happens.

1. The Real Problem Is That Progress Lives in the Conversation

By default, where does the fact "six items are done" live? Only in the transcript. When the session ends, it goes with it.

Worse, the output usually goes too. If the agent planned to write all eight items and commit once at the end, an interruption at item five and a half leaves nothing at all.

This shape: interruption = total loss write 1 → write 2 → ... → write 8 → commit → push ↑ die here and you have zero This shape: interruption = progress preserved 1 → verify → commit + push 2 → verify → commit + push ... ↑ die here and everything before survives

The principle is old and simple: put every completed unit into durable storage immediately. For agent work, durable storage means a commit and a push.

2. Commit the Plan First

Then go one step further and persist the plan before any output.

The scheduled posts on this blog are drafted in batches by an agent. The first thing that agent does is not write a post — it writes and commits a .content-queue.md.

## Batch 2026-08-06 | # | publish | track | slug | done | |---|------------|-------|-------------------------------|------| | 1 | 2026-08-22 | A | eleventy-scheduled-publishing | [x] | | 2 | 2026-08-25 | B | claude-md-agent-rules | [x] | | 3 | 2026-08-27 | C | zone2-cardio-heart-rate-guide | [ ] | | 4 | 2026-08-30 | A | locale-symmetry-build-guard | [ ] |

With that file present, the next session reconstructs the state without any transcript: what was decided, how far it got, what remains — all of it in the repository.

There's a useful side effect. Writing the plan down first means the agent can't quietly change direction mid-run. Start without one and item six is often something nobody intended.

Plans are cheaper than output and disappear first.

A post can be rewritten. "Why these eight, in this order" is much harder to reconstruct. Persist the cheap, fragile thing first.

3. One Commit Per Work Item

When to commit is the whole game, and the rule is one line: the moment an item passes verification, commit and push it.

Critically, the output and the progress marker go in the same commit.

git add src/ko/posts/{slug}.njk \ src/en/posts/{slug}.njk \ .content-queue.md ← the checkbox too git commit -m "feature: ..." git push

Split them and you create a window where they disagree. Die with the post committed but the checkbox unticked and the next session writes that post again. One commit closes the window.

Push every time as well. When the execution environment itself is reclaimed, local commits go with it — a local commit is not a checkpoint.

4. Separate START from RESUME

For resumption to work, the agent has to know whether this is new work or continuation. So we made the run mode explicit.

MODE: START If an unfinished batch exists, finish it before starting a new one. Otherwise, plan a new batch. MODE: RESUME No unfinished batch → do nothing and exit immediately. Unfinished batch → check out its branch and continue from the first incomplete item. Never redo an item already marked done.

That first RESUME line matters more than it looks. With nothing to do, the correct behavior is to do nothing and stop.

Left unstated, an agent will find something to do — producing work reads as more helpful than returning empty-handed. So it starts a batch nobody asked for. On a task that fires automatically, that repeats quietly, forever.

"If there's nothing to do, exit immediately" has to be written down.

It is not the default behavior. A few harmless-looking empty runs later, you have output nobody planned.

5. Completion Must Be Observable

Resumption requires deciding "is this item done?" from files, not from a transcript.

Two signals back each other up here:

  • The checkbox[x] in the queue file is the primary record.
  • File existence — if src/{ko,en}/posts/{slug}.njk exists, it was really produced.

When they disagree, believe the files. The checkbox is a record; the file is the fact. Disagreement is rare anyway, since they ship in one commit.

This structure also buys idempotency. Run the same session twice and the second run skips everything already complete. On anything that fires on a schedule, duplicate runs are guaranteed — so this isn't optional.

6. Verify Per Item Too

Having split commits by item, split verification the same way. Write all eight and build once at the end, and a failure means hunting for which item caused it. Worse, an interruption leaves unverified output behind.

write item 1 → npm run build → pass → commit + push ↘ fail → fix, rerun → commit only on pass

The rule is never commit an item that hasn't passed. Then every commit in the repository is a state where the build is green, and whatever survives an interruption is entirely valid.

This site fits the pattern well because the verification lives in the build. When checking is one command, running it per item costs almost nothing.

7. What to Put in the Rules File

Surprisingly little is needed to keep this running. The agent rules file says roughly this:

- Commit the plan first. The plan lands before any output. - The moment an item passes verification, commit and push it. Do not batch several items into one commit. - Mark that item done in the queue file in the same commit. - Never redo an item already marked done. - On RESUME with no incomplete items, exit immediately.

Without that second line, an agent will batch its commits — to a human eye that's the tidier history. But once you assume interruption, frequent checkpoints beat a tidy log.

8. In Summary

These are old principles: checkpoint your batch jobs, make units of work atomic, make re-runs safe. Agents don't change any of that.

  • Keep progress in the repository. In the conversation, it dies with the session.
  • Commit the plan before the output. The plan is the hardest part to regenerate.
  • One item = one verification = one commit = one push, with output and progress marker together.
  • Make completion decidable from files. That's what makes re-runs safe.
  • Say explicitly that no work means exit. It isn't the default.

If you're handing an agent long tasks, ask what would survive if this session ended right now. If the answer is "nothing," the structure needs fixing before the task does.