Product Thinking

Your docs rotted the moment you merged

Documentation goes stale at the speed of code. An agent that watches the diff and flags the now-wrong doc turns documentation from a debt you pay down into a thing that stays alive.

ASR

Apollo Space Research

Apollo Space

· 11 min read

A function was renamed on a Tuesday. The README still calls it by the old name. The onboarding doc still shows the old signature. The runbook still tells the on-call engineer to run a flag that no longer exists. Nobody touched any of those three files, and that’s the point. They didn’t change. The code under them did. So they stopped being true the second the pull request merged, and not one person noticed.

That gap, between the code that moved and the doc that didn’t, is where documentation goes to rot.

We tend to talk about stale docs as a discipline problem, as if the cure were a stricter rule: always update the docs when you change the code. It isn’t a discipline problem. It’s a timing problem. The doc didn’t get wrong because someone was lazy. It got wrong because nothing was watching the diff at the moment the diff happened. The fix is not a rule. It’s a watcher.

Docs rot at the speed of code, and a rule won’t save them

Here’s the naive model, the one every team starts with. Documentation is a thing you write once and update “when needed.” You keep it next to the code, you ask people to be good citizens, and you trust that a careful engineer who renames a function will also go fix the README, the architecture doc, and the four guides that mention it.

It works for about a week. Then it doesn’t, and the reason is structural, not moral.

Code changes constantly and in tiny increments. A doc is a snapshot. Every commit nudges the code a little further from the snapshot, and nobody can see the drift because the drift is invisible, the doc still renders, still reads cleanly, still looks done. A wrong doc and a right doc are pixel-for-pixel identical until someone trusts the wrong one. There’s no red squiggle under a sentence that used to be true. The compiler doesn’t care. The tests don’t care. Prose has no type system.

So the gap widens silently, and the cost lands later, on someone who wasn’t there. The new hire who follows the setup guide into a wall. The on-call engineer who runs the documented command at 3 a.m. and watches it fail. The teammate who builds against an API the doc promised and the code no longer offers. Every one of them pays for a change they didn’t make, because the doc that should have warned them was quietly wrong.

The rule, “update the docs”, fails for the same reason all good-citizen rules fail. It asks a tired human, mid-task, to remember a second job that has no deadline and no alarm. The doc didn’t go wrong because someone forgot. It went wrong because nothing was watching the diff.

That sentence is the whole thesis, so let’s say it plainly and then build the machine that makes it false.

The watcher reads the diff, not the calendar

The obvious instinct, once you admit the rule won’t save you, is to schedule an audit. Once a quarter, somebody reads the whole docs folder and fixes what’s stale. This is better than nothing and worse than it sounds.

A calendar audit is the wrong clock. It fires on a date, but docs don’t rot on a date, they rot on a commit. By the time the quarterly review comes around, the drift has been live for weeks, the new hire already hit the wall, and the reviewer is trying to reconstruct which of two hundred commits broke which of fifty docs. You’re asking a human to diff three months of code against a folder of prose, from memory, in an afternoon. Nobody does that well. Mostly, nobody does it at all.

The right clock is the diff itself. The moment a change lands, that is the moment to ask: did this just make a doc wrong? Not in three months. Now, while the author still has the change in their head and the cost of fixing the doc is one more line in the same pull request instead of an archaeology project next quarter.

So the watcher doesn’t run on a schedule. It runs on every change. When a pull request moves a function, a flag, a config key, an endpoint, an error message, the watcher reads that diff and asks one narrow question of the documentation: does anything we wrote down still claim the old thing is true?

A pull request renames a function. On the naive path the doc is left untouched and silently goes stale until a new hire trusts it and hits a wall. On the watcher path an agent reads the same diff, finds the README that still names the old function, and flags it on the pull request before merge.

The key idea is simple, so let’s name what makes it work. The watcher is not “an AI that writes docs.” It’s an agent pointed at two things at once, the change and the corpus of what you’ve already written, whose entire job is to find the contradiction between them. It already knows the README mentions the function, because it can read the README. It can see the function was renamed, because it can read the diff. The match is the alert. This file says chargeCustomer. This commit deleted chargeCustomer. Look here.

That’s the difference between a watcher and an audit. The audit hunts through everything hoping to find drift. The watcher is handed the exact change and only has to ask what that one change broke. The search space collapses from “the whole docs folder” to “the handful of docs that mention the thing that just moved.” Small question, answered now, by the only party who can see both sides of the gap at the same moment.

Flag, don’t autocorrect, the human keeps the pen

There’s a tempting overreach here, and it’s worth refusing out loud, because it’s the version most people imagine when they hear “an agent that fixes your docs.”

The overreach is: let the agent rewrite the doc automatically. It sees the rename, it patches the README, it commits the fix, done. Clean, autonomous, and wrong in a way that’s hard to see until it bites.

The problem is that a doc carries intent, not just facts. The function was renamed, fine, the watcher can swap the name. But why was it renamed? Maybe the new name signals a new contract, a new caveat, a behavior change the old sentence around it no longer describes. An agent that mechanically swaps the identifier produces a doc that is now syntactically current and semantically lying, which is strictly worse than a stale doc, because a stale doc at least announces its age by mentioning a name that no longer exists. A silently auto-patched doc looks fresh and reads wrong, and now nobody’s watching it because the watcher already “handled” it.

So the watcher doesn’t autocorrect. It flags. It says, on the pull request, in front of the human who made the change: this README references the function you just renamed; this guide shows a flag you just removed; this architecture note describes a flow you just rerouted. It points at the gap. It can draft a suggested fix. But the pen stays in the human’s hand, because the human is the one who knows whether the rename was cosmetic or load-bearing.

This is the same discipline a good agent uses everywhere in Apollo. The machine does the watching, the tireless, boring, 100%-coverage part that humans are structurally bad at. The human does the deciding, the judgment call about what the change means, which is the part that was always the actual job. The watcher turns “remember to check fifty docs” into “approve or edit three suggestions, right here, with the change still warm.” It moves the cost from later-and-expensive to now-and-cheap, and it never moves the authorship.

There’s a quieter benefit, too. Because the flag lands on the pull request, the doc fix and the code change ship together, reviewed together, by the same person who understands both. The doc stops being a separate chore that lives in a separate backlog and starts being a property of the change, as inseparable from the merge as the tests are.

Three lanes for keeping docs true. The good-citizen rule asks a tired human to remember a second job and fails silently. The quarterly audit fires on the calendar, weeks after the drift went live. The diff-driven watcher fires on the commit, flags only the docs the change touched, and hands the human a ready edit before merge.

Why “gardening” is the right word, and “writing” is the wrong one

People ask whether an agent can write their documentation, and that’s the wrong question, because writing was never the expensive part. Anyone can write a doc. A model can certainly draft one. The expensive part, the part that bankrupts every documentation effort eventually, is keeping a doc true after the world it described has moved on.

A garden is the honest metaphor. You don’t write a garden once. You don’t audit it quarterly, either, or it’s a field of weeds by spring. You tend it continuously: you notice the thing that’s overgrowing the path, you pull the weed while it’s small, you catch the drift before it becomes a mess. The work is constant, low-stakes, and exactly the kind of attention humans run out of first, which is why gardens left to good intentions die.

That’s documentation. Not a writing problem, a tending problem. The doc didn’t go wrong because someone forgot. It went wrong because nothing was watching the diff. A gardener is just a watcher with a purpose: it sees what the last change disturbed, and it pulls the weed, the now-false sentence, before anyone trusts it. The corpus stays alive not because someone rewrote it, but because something never stopped tending it.

And once you have a watcher reading every diff against the whole corpus, gardening is the smaller half of what it can do. The same agent that notices a doc went stale can notice a doc was never written, the new endpoint nobody documented, the config key that appeared with no explanation, the runbook step that exists in code and nowhere in prose. The drift it catches isn’t only “the doc says something false.” It’s also “the code says something the docs never mentioned.” Both are gaps between what’s true and what’s written down. The watcher closes both, the same way, by speaking up at the moment the gap opens.

The turn: who pays for a stale doc, and who stops having to

Step back from the mechanism and look at who actually carries the cost of documentation rot, because it’s never the person who caused it.

The engineer who renamed the function moved on, correct in their own context, never wrong for a second. The cost landed downstream, days or weeks later, on someone with less context and no warning: the new hire on day three, the on-call engineer at 3 a.m., the teammate who trusted the API doc and lost an afternoon to a promise the code no longer kept. Stale docs are a tax with the cruelest possible incidence, the person who can least afford the confusion pays for a change they never saw.

A watcher that reads every diff doesn’t make documentation effortless. It makes it current, which is the only property that ever mattered. A current doc is a colleague who tells you the truth. A stale doc is a colleague who confidently tells you something that stopped being true last Tuesday, and you can’t tell the difference until you’ve already trusted them. The whole value of writing something down is that the next person can rely on it. The moment it might be lying, that value is gone, and a doc that nobody can rely on is worse than no doc at all, because at least no doc doesn’t pretend.

So the question isn’t whether an agent can write your documentation. It’s whether anything is watching the gap between what your code does and what you wrote down it does, and whether it speaks up at the moment the gap opens, while the fix is still one cheap line, instead of months later, in front of the person least equipped to catch the lie.


That’s what we’re building at Apollo: not a smarter doc editor, but a watcher that reads every change against everything you’ve written and pulls the weed before anyone trusts it. If you’ve ever followed a setup guide straight into a wall, you already know the doc wasn’t lazy. It was just unwatched.

Apollo runs your company's repetitive ops so your team doesn't.

Join the waitlist for early access, founding-user pricing, and a front-row seat as we ship.

Join the waitlist