Processes · Knowledge-driven development, part 4 of 5
What it replaces
Knowledge-driven development, part 4: a short obituary for the ticket
Seeded September 2026 Written October 2026
Knowledge-driven development is an experiment of mine, and it isn't battle-tested yet. Part 1 says where it started.
Most of what knowledge-driven development does, it does by deleting something. The TODO folder went first. The work orders went next. Then my backlog, my sprint board and most of what a ticket tracker is for.
They were all designed for a team of humans who remember things between Monday and Thursday. That's not the team I have any more. But each of them did something useful, and the useful part had to go somewhere when the rest went in the bin.
1. The ticket tracker
A ticket tracker keeps the intent outside the repository, which is why it drifts. For agents, it's worse than drift. A ticket is invisible at the moment of editing. The agent changing the code never sees it, however carefully someone wrote it.
And it usually wasn't written carefully. A typical ticket looks like this:
Export fails sometimes
Accounting says some nights the export is missing. Can we look at this?
That's a subject line and a shrug. It doesn't say what the export should do, what "missing" means, or what anyone has already tried. Hand it to an agent, and the agent will fix something.
The same problem, in the knowledge document that describes the export:
❌ When the accounting system is unavailable at 02:00, the export retries every 15 minutes, and the night's records are sent once it's back.
⚠️ If the export still hasn't succeeded by 06:00, the operator on call gets an alert.
The ❌ says the retry exists and doesn't work. The ⚠️ says the alert hasn't been built yet. Neither explains itself, because the sentence is the specification, and an agent can build from it. Both sit in the page an agent reads before it touches the export.
On my team, who is me and a fleet of agents, and when is now. So the tracker doesn't own anything the code depends on. My agents still keep Asana up to date for the project managers and product owners who use it, but nothing in the repository ever reads it back. It's a second map, and they only ever write to it.
The project managers loved the status updates, which are current and tailored to what they need. Then they had a heart attack over the number of tasks the agents had added to the current sprint. Now the agents keep only the major work items in the sprint. The countless microtasks go into the knowledge documents, not into Asana, and the Asana task refers to the document instead of repeating it.
Many of those microtasks aren't worth keeping at all: an agent can work out the small steps for itself when it implements the feature. And once a microtask is done, the code is the record of it.
2. The TODO comment
TODO is a mark that failed to say anything. It records that somebody was unhappy at that line, and nothing else: not whether the code works, whether it's broken, what it should do instead or who could fix it.
Like plenty of other programmers, I've stumbled over this periodically since the stone age of computing: a few hours spent debugging yet another production problem, and then the TODO comment that had identified it all along.
So every TODO comment in the source moved into the knowledge document that owns its code, as a ⚠️ or ❌ that says what the comment never did. Before:
// TODO: handle timeouts
var result = await accounting.SendAsync(batch);
After, in the export's document:
❌ When the accounting system doesn't answer within 30 seconds, the export abandons the attempt and schedules a retry.
The comment knew there was a problem, and kept it to itself. The sentence says what the system should do about it, in the place someone will read it.
The knowledge-driven vocabulary is TODO with a type system and a reader in mind. ⚠️ says it isn't built and describes what it should be. ❌ says it's built wrong and states the correct behavior. ⛔ says why it can't be fixed from here, and what would unblock it.
So TODO isn't discouraged. It's a build failure.
3. Plans and work orders
My agents used to write work orders: numbered steps, each with its own definition of done, the riskiest first and the parallel ones marked. A step looked like this:
Step 4 of 7. Add retry logic to
ExportJob: every 15 minutes until 06:00. Done when the unit tests pass. Can run in parallel with step 5.
The same intent, written the knowledge-driven way:
⚠️ When the accounting system is unavailable, the export retries every 15 minutes until 06:00.
The step was true for one afternoon. Once it was done, it described a piece of history that nobody would read again. The sentence stays true for as long as the export works that way, and the day someone changes the retry interval, the sentence changes with it.
The ordering and the notes about what can run in parallel went too. The implementing agents work those out from the documents, like everything else, which is the subject of part 3.
4. Specs and README-driven development
README-driven development was the right idea at the wrong scale. A README is one document for one audience: the person deciding whether to use the thing. It says nothing about how the system fails, how to operate it, or what's half built. It covers the front door. Knowledge-driven development is the same idea applied to every audience at once, with marks, so the documents survive past version 0.1.
Spec-driven development has the opposite problem. The spec is a separate artifact, read once by the agent that implements it and never again. Six months later, the spec says what the feature was meant to be in March, and the code says what it became. Nobody reconciles the two, because nobody opens the spec. In knowledge-driven development, the spec is the manual, and it keeps being read, because it's what people and agents open to find out how the system works. Being read is the only thing that has ever kept a document current.
5. Release notes and onboarding
These fall out for free. The release notes for a change are the marks that moved. For the export fix above, they're the diff to one page:
✅ When the accounting system doesn't answer within 30 seconds, the export abandons the attempt and schedules a retry.
✅ When the accounting system is unavailable at 02:00, the export retries every 15 minutes, and the night's records are sent once it's back.
⚠️ If the export still hasn't succeeded by 06:00, the operator on call gets an alert.
Two fixed, one still to build. Nobody had to write that up, and nobody had to check that the write-up matched the code.
Onboarding is reading the documents for the part of the system you're about to touch. They're the only description of the system there is, and they say what doesn't work.
A new engineer, human or otherwise, doesn't have to learn which parts of the wiki to trust. They can grep for the parts not to.
6. What stays
Architecture decision records and the changelog stay. They record the past, and the past doesn't drift. They never get marks, because a ✅ in a document about the past would be a claim about the present in the wrong place.
Executable specifications stay, and win where they apply. A doctest or a Gherkin scenario can't drift, because it's a test. Where a statement can be a test, make it a test and drop the mark. Knowledge-driven development is for the rest: things that aren't executable yet, things that are broken, things about people rather than code.
Literate programming was never in the running. It needs its own toolchain, and nobody maintains the prose half.
Everything I deleted was a second description of the system, kept somewhere other than the system and updated by some act other than changing the code. All of it drifted, and the people it was written for stopped reading it.
The ticket had a good run. It just never had a reader who mattered as much as the agent that couldn't see it.