Revert Is Cheaper When the Author Cannot Explain Itself

Read22 min · Scope → Isolate → Supervise → Land · Updated 2026-09-13

You end this lesson with: fleet/rollback.md — the revert-or-patch-forward decision rule for agent-authored change.

Chapters

  1. What is actually going on
    01
  2. The rule and its condition
    02
  3. Worked case
    03
  4. Faded case
    04
  5. Open case
    05
  6. Where this breaks
    06
view

Lesson 16. Revert Is Cheaper When the Author Cannot Explain Itself

A production bug traces back to a change an agent made nine days ago. The pull request body is three sentences, the tests it wrote pass, and the session that wrote it closed itself out after merge, the way sessions do. Your first move, the one you would make for a change a colleague wrote, is to ask the author what they were thinking. There is no author to ask. You open a fresh agent, point it at the diff, and ask it to explain the reasoning behind the change. It answers immediately and completely: it names the bug it was fixing, the edge case it considered, the trade-off it made. The explanation is fluent, specific, and entirely invented. The fresh agent never saw the original task, the original context, or the original reasoning; it is pattern-matching a plausible story onto a diff it is reading for the first time, the same way it would explain a diff from a stranger's repository it had never seen before. Your team reads the explanation, nods, and starts patching around it. Decide now: what do you actually know about why this change exists, and how much of it did you just make up together?

This lesson's deliverable is fleet/rollback.md — the revert-or-patch-forward decision rule for agent-authored change. It closes the Land stage of Scope, Isolate, Supervise, Land: the last decision before a change either stays merged or gets pulled back out.

What is actually going on

What just happened when the fresh agent explained the old diff has a name worth being precise about: it produced a reconstruction, not a recollection. A human author asked the same question nine days later is also reconstructing, since memory degrades, but they have something the fresh agent structurally cannot have: they were there. They remember the failed attempt that came before the one that shipped, the message from a teammate that changed their mind, the constraint that never made it into a comment. A fresh agent reading only the diff has none of that. It has the code before and the code after, and a language model is extremely good at generating a plausible story that connects the two, good enough that the story reads as confident and specific, which is exactly what makes it dangerous. Confidence and specificity are not evidence. They are the model doing what it always does: producing the most likely continuation of the text in front of it. The task spec, the tool calls, the rejected alternatives, the actual reasoning, lived in a session that is gone.

This is why the default for agent-authored change should be revert-and-rerun, not patch-forward, and the reason is mechanical rather than a general appeal to caution: patching forward requires understanding intent, in order to know which parts of the code are load-bearing and which were incidental. Intent is precisely what an agent-authored change cannot supply after the session ends. Re-running from a corrected task spec sidesteps the whole problem: instead of interrogating a diff for reasoning it never really had, you write down what should have been true the first time and let a new run produce a new diff with the intent stated up front, not inferred backward.

Two different rewind mechanisms sit under this rule, and mixing them up costs you the cheap one. In-session checkpoint and rewind, jumping a still-open session back to an earlier state without leaving the conversation, is available only before merge; it is nearly free, and it is the right tool for "that last step went wrong, back up." Version-control revert is what is left once the session is gone and the change already merged; it is not free, because reverting a merged change can itself conflict with whatever merged after it. The diagram below shows the revert-and-rerun path once the cheap option is off the table.

diagram
drawing
Once a session is gone, the cheap fix is a new run against a corrected spec, not a conversation with the old diff.

The rule and its condition

Use revert-and-rerun when the change is recent, nothing already depends on it, no data migration has run against it, and a run record exists to correct into a new spec, or writing a fresh spec from scratch is still cheap even without one. Use patch-forward only when reverting costs more than the revert-and-rerun path buys you: when the change has already been built on, or undoing it means undoing real work along with the bug.

ConditionRevert and rerunPatch forward
Age of the changeHours to a few days: little has been built on itWeeks: enough has shipped on top that reverting drags dependents with it
Downstream dependentsNone, or dependents are also cheap to re-runReal, hand-written work sits on top of the change
Data migrationsNone ran, or the migration is itself reversibleAn irreversible migration already ran against production data
Run recordSurvives: correct the existing task specLost: write a spec from scratch, which still favors revert unless another condition already flipped it

The four conditions rarely agree cleanly, so treat them as a filter, not a vote: a downstream dependent by itself does not flip the decision if re-running the dependent is itself cheap, since it is an agent-authored dependent too, but an irreversible data migration flips it on its own, because there is no revert that undoes a write that already happened. Walk the tree in this order: age, then dependents, then migration, then record. Each earlier question can end the search before you reach the harder ones.

diagram
drawing
Each condition can end the decision early; an irreversible data migration is the one condition that flips the rule on its own.

Worked case

Voss Analytics ships a metrics pipeline that an agent modified nine days ago: a pull request titled "fix duplicate event counting in the ingest worker," merged after its gate passed, three files changed, three tests added. This morning a customer reports their dashboard is undercounting events. Git blame points straight at the nine-day-old merge. The on-call engineer has two candidate moves: read the diff and patch the dedup logic in place, or revert the merge and re-run the original task with a corrected spec. Decide now, before the reveal: which one, and what single piece of evidence should decide it?

Illustrative composite. Voss Analytics, its ingest worker and the specific figures in this case are invented for teaching; the reconstruction failure mode is real and documented across the practitioner sources this lesson draws on. The undercount the customer reports is roughly 4% of events.

The on-call engineer's first instinct is to ask a fresh agent session to read the diff and explain what it was trying to do. The session answers without hesitation: "This change deduplicates events by a composite key of user ID and timestamp, because the ingest worker was previously counting retried webhook deliveries as separate events. The comparison window was set to 500ms based on typical retry latency." It is a good answer. It is also invented: nothing in the diff, the pull request description, or the commit message mentions a 500ms window, retry latency, or a composite key at all. The fresh agent generated a plausible mechanism for a deduplication fix because that is what deduplication fixes usually look like, not because it read anything that said so. The on-call engineer nearly patches the actual, nonexistent 500ms window before checking the run record.

The run record for the original run, the one fleet/audit/ from lesson 14 exists to produce, tells a different story. The original task spec asked the agent to "stop counting the same webhook delivery twice when the provider retries." The agent's tool calls show it read the webhook handler, not the ingest worker, and its actual fix compared delivery IDs, not a timestamp window. The bug is that the fix only covers the direct webhook path. A second ingestion path, a batch backfill job, delivers the same events through a different code path that the original task never mentioned, and the agent, reasonably, given a scope it was never told to check, never touched it.

That single fact decides the case. This is not a bug in the nine-day-old change; the change does exactly what it was asked to do. It is a bug in the task spec, which scoped the fix to one ingestion path and left another path with the same defect. Patching the merged diff would mean guessing at a fix for a problem the diff was never about, in code the diff never touched. That is exactly the kind of blind patch that "ask a fresh agent what it meant" tempts you into.

The correct move is revert-and-rerun. The nine-day-old merge is not itself wrong, but that does not matter: what matters is whether anything depends on it, and here nothing does, since the pipeline only reads its output and no other change has built on top of it. Revert it, write a corrected task spec that names both ingestion paths, and dispatch a fresh run against the corrected spec.

The entry in fleet/rollback.md for this incident:

markdown
## 2026-09-02 · Ingest dedup undercount

- Original merge: PR #418, 9 days old, agent-authored, gate passed
- Downstream dependents: none (dashboard reads only, no code built on the diff)
- Data migration: none
- Run record: survives (fleet/audit/2026-08-24-pr418.md)
- Decision: revert and rerun
- Reason: original task spec scoped to one of two ingestion paths; the
  merged diff correctly does what it was asked, the spec was incomplete
- Corrected spec: dedup on delivery ID across both the webhook handler
  and the batch backfill path
- Rejected: patch-forward — would have required guessing at backfill-path
  logic the diff never touched, from a diff that gives no evidence about it

Notice what decided the case: not a vote among the four conditions, but one of them, the run record, settling the question the fresh agent's confident guess could not.

Faded case

Skip to the open case if this is familiar.

Ferrous CI, a build-tooling startup, has an agent-authored change from six days ago that reworked their cache-key generation for build artifacts. A flaky-build report traces intermittent cache misses back to it. Two other agent-authored changes have merged on top of it since: one added a new build target, one added a metrics counter for cache hit rate. Both touch the same cache-key module, both pass their own gates, and neither is aware the base change has a bug.

Run through the four conditions. Age: six days, inside the window that usually favors revert. Downstream dependents: two changes, both real, both merged against the buggy version, both in the same module. Data migration: none, since cache keys are regenerated on every build and nothing persists. Run record: survives for all three changes, task specs and tool calls intact for each.

Illustrative composite. Ferrous CI and its build-tooling specifics are invented for teaching.

One condition here does more work than the others. Age says revert. The run record surviving says revert would be cheap to redo. No migration means nothing is irreversible. But two real changes are stacked directly on top of the buggy one, in the same file, and reverting the base change means reverting or rebasing both of them too, work an agent did on legitimate new functionality, not on the bug.

Decide: revert-and-rerun, or patch-forward, and which single condition made the call?

Open case

Talleres Reyes, an inventory-management SaaS, has an agent-authored change from eleven days ago that altered how a warehouse-transfer record calculates its committed-stock number. A customer's inventory count is now visibly wrong. Since the change merged, a data backfill job has run twice against the live committed-stock column, correcting historical records to match the new calculation. No other change has merged against the transfer-calculation module. The run record for the original change is missing: the agent that wrote it ran under a configuration that did not retain run records, a gap the team fixed the week after. Write the fleet/rollback.md entry: revert-and-rerun or patch-forward, and which condition decided it.

Where this breaks

The rule assumes reverting stays cheap, and that assumption is something you have to protect earlier, not something the rule guarantees on its own. A merge with a large blast radius, many files, several unrelated concerns bundled into one agent run, makes "downstream dependents" almost always yes, which pushes you toward patch-forward by default even for a change you would otherwise happily throw away. Lesson 13's merge policy exists partly for this reason: keeping each merge small and scoped to one artifact is what keeps the fourth question in the flowchart from becoming the answer every time.

The rule also assumes you can tell the difference between a fresh agent's confident reconstruction and real evidence, and that distinction gets harder, not easier, as the reconstruction gets more detailed. A short, vague explanation is easy to distrust. A long, specific one, file names, line numbers, a plausible-sounding design rationale, reads exactly like evidence and is generated by exactly the same mechanism as the short vague one. Treat length and specificity as properties of the model's writing, not as a confidence signal about the past.

Finally, a missing run record does not mean the rule stops applying; it means the fourth question costs more to answer. You still revert, then write the corrected task spec from the diff and the bug report instead of from a preserved original, which takes longer and is more likely to miss context the original session actually had. That is a reason to fix the gap lesson 14 addresses, not a reason to trust a fresh agent's account of the gap instead.

Key Takeaways

  • Bias toward revert and rerun for agent-authored change; patch-forward needs intent a diff cannot supply after the fact.
  • Treat a fresh agent's explanation of an old diff as invented, not recalled, however confident it sounds.
  • Walk age, dependents, migrations, run record in order; an irreversible migration decides alone.
  • Use in-session checkpoint and rewind before merge; it costs almost nothing. Version-control revert is the expensive fallback.
  • Keep merges small so "downstream dependents" does not default to yes and drag the whole rule toward patch-forward.
  • Correct the existing task spec when the run record survives; write one from scratch, slower, when it does not.

What You Have Now

fleet/rollback.md — the revert-or-patch-forward decision rule for agent-authored change. It lives in your growing Fleet Kit next to fleet/merge-policy.md, which it leans on directly: a merge policy that keeps blast radius small is what keeps this lesson's decision tree resolving toward revert-and-rerun instead of defaulting to patch-forward by size alone. It also depends on fleet/audit/ from lesson 14 existing and being populated: the fourth condition in this lesson's flowchart is unanswerable without it. This closes the Land stage: every earlier Land-stage lesson decided how a change gets in; this one decides what happens the day one of them turns out to be wrong.

Further Reading

Exercises

  1. Pick one agent-authored change already merged into a repository you use, or a deliverable from an earlier lesson in this course. Walk it through the four conditions and write the fleet/rollback.md entry, real or hypothetical.
  2. Ask a fresh agent session to explain a diff it has never seen, your own or the Voss Analytics diff above, without giving it the original task. Compare its explanation to the actual task spec or pull request description, line by line, and note exactly where it invented detail.
  3. Extend fleet/merge-policy.md from lesson 13 with a rule that keeps a single merge's blast radius small enough that "downstream dependents" rarely forces patch-forward. State the rule as something you can check mechanically, a file count or a module boundary, not a guideline.

Check your understanding


Reading is free — your progress isn't being saved

Nothing you did on this page is recorded. Paid students get saved progress and verified completions, recorded quiz answers, the spaced-repetition review queue, labs, and a certificate for each course they finish.

30-day money-back guarantee. One-time payment — lifetime access and updates.