← All posts
June 29, 20264 Min ReadRepoOps Team

Markdown doesn't rot. Unverified markdown does.

A sharp argument is going around that AI agents built on piles of prompts and docs fall apart the moment production changes. It is right about the disease. We think it is slightly wrong about the cure — and we just fixed a textbook case of it in our own codebase.

There's an argument going around that's worth taking seriously, because most of it is right.

It goes like this. Teams building DIY AI agents for production connect a model to their observability tools, wire up some MCP servers, and pile on prompts, skills, and markdown until the thing seems to understand the system. And it works — until production changes. Services ship, ownership moves, dependencies evolve. Six months later the agent is reasoning from stale docs and half-remembered context: a graveyard of markdown masquerading as knowledge. The conclusion: this is a representation problem, not a tooling one. Production is a living system, and a pile of hand-maintained docs can't represent something that changes every day. The bottleneck is the data layer — agents need an understanding built continuously from telemetry, code, dependencies, and live state, not from markdown engineers are supposed to keep current. Otherwise you're asking a model to reason about a system it can't actually see.

We agree with almost all of it. We'd just sharpen one word.

It isn't markdown that rots

It's unverified markdown that rots.

Markdown a human is expected to keep current always drifts, because keeping it current is unpaid, invisible work that loses to shipping every time. But markdown derived from the live system and gated so it can't drift isn't a liability — it's a cache. The file format was never the problem. The problem is whether the representation is reconciled against ground truth, or just hoped to be.

So "stop writing things down" is the wrong lesson. Some of what an agent needs to know — why a decision was made, what an incident taught you, which path you chose not to take — can't be reconstructed from telemetry. It exists only because a human wrote it down. You don't delete that. You fence it off from the parts that can be derived, then make those parts actually derived and gate them so they can't lie.

The real question isn't "markdown or no markdown." For every fact your agent relies on: is it generated from the source and verified, or asserted in a doc and trusted? Everything in the second bucket is a future outage of confidence.

It isn't the markdown that rots. It's the part you were supposed to keep current — and didn't.

What that looks like when you build it

continuously; the dependency graph and the blast-radius of a change are extracted from the source, not typed into a doc someone promises to update.

computed from the live stream. Nobody writes "our cache hit rate is good" in a file; the number is read off the data, or it doesn't exist.

prose, walled off from the factual layer so a stale note can't corrupt a live contract. Lessons promote themselves: a defect found once becomes a rule automatically, and a rule that stops being true drops back out.

are derived from code have CI gates. If the code and the doc disagree, the pull request fails — the merge is blocked until they match.

  • Code and live state are read, not described. Repos are mirrored from origin
  • Telemetry is derived, not summarized. Cost, cache-hit rate, routing, risk —
  • The narrative layer is kept, but fenced. Decisions and lessons stay as
  • Drift is a build failure, not a chore. The parts of our knowledge base that

That last one is the whole game. A representation you hope is current and one that fails the build when it isn't are different species, even when they're the same file.

The graveyard in our own house

Here's the part that keeps us honest. We keep a machine-readable map of our own codebase — the thing a fresh agent reads to orient itself. For a long time its routes section was hand-maintained, with a polite comment at the top: "update this in the same pull request as any change to routes."

You already know how this ends. We checked, and the map was badly out of date — it documented a small fraction of the routes the server actually answered. Our own living map of our own system had quietly become mostly fiction, sitting in the middle of a product whose entire pitch is "don't let your knowledge drift."

So we fixed it the way the argument says you should: we made it derived. A small generator now parses every route straight out of the server and rewrites the map, keeping the human-written descriptions where they exist. A CI gate runs it in check mode — add a route to the server without regenerating the map, and the build goes red. It can't drift again, because drifting is now a failing test. The gap wasn't laziness; the map was in the "asserted and trusted" bucket, and everything there drifts. The fix wasn't more discipline. It was moving the fact into the other bucket.

The honest version of the lesson

Stop asking the model to reason about a system it can't see. That part is just right, and the data layer really is the bottleneck. But don't read it as "docs are the enemy." Every fact your agent depends on should be derived from the source and gated against drift — except the handful of things only a human can know, which you keep on purpose, fenced where they can't poison the rest.

Markdown doesn't rot. The stuff you were supposed to keep current and didn't — that rots. The cure isn't deleting the docs. It's making the system write them, and failing the build when reality and the page stop agreeing.