RSS Amplifier

Keith Sinclair · Apr 28, 2026

The Bottleneck of Vibe Coding: Preserving Software Intent

0
Sign in to vote or save

Keith Sinclair · Keith Sinclair

Vibe coding works beautifully for the first week.

By the third month you are maintaining a stranger’s codebase. The stranger is partly you and partly a robot that has since forgotten the conversation. Half the commit messages say, “fix login,” the other half say “wip.” You ask the only question that matters, the question every maintainer eventually must ask, which is why is it built this way? Nobody answers. Not the code, not the git log, not the agent that wrote half of it, not you.

That moment, the moment the code outruns the conversation, is what I want to talk about.

I have been there before, in a slower form. Thirteen years ago, I started work on opEvents at Opmantek, later acquired by FirstWave. It is still running in production today; in places I would not have predicted when I started writing it.

What I remember about building it is almost nothing about the code. I remember the conference calls with customers, hearing the same need over and over, walking out with ideas that needed running code behind them. Opmantek was still small. I was switching between delivering services, attending sales calls, sitting in board meetings, and writing the product itself.

I took the PowerPoint of my ideas and started coding. The prototype took four weeks. The PowerPoint kept evolving the whole time, a living document I rewrote every time a customer call shifted what mattered. Then the wiki pages took another four weeks on top, turning the deck into the documentation that would carry the product after I stopped touching it. Over a decade later the PowerPoint and the wiki pages are still doing the most important job an artefact can do in a software project. They are telling the next person why.

That is the inversion vibe coding has handed us. opEvents got built when typing was slow and thinking was the easy part of the day. Vibe coding is the opposite. Typing is instant, generation is instant, and now thinking is the only thing left that takes any time at all. The bottleneck moved. Most teams have not noticed yet.

Share

The bottleneck has always been specification, not execution. Vibe coding just made it obvious, by removing the only thing that used to slow projects down enough for thinking to catch up. The code is the cheap part. Agreement on what the code should be is the expensive part. The more capable the worker, the more expensive a vague brief becomes, because they execute on it faster and deeper before anyone notices.

I have watched this play out with every kind of worker.

A graduate dev, eager and quick, ships exactly what you asked for, which turns out to be exactly what you asked for in the words you used, not what the customer needed. You spend a fortnight refactoring once the customer sees it.

A contractor on a fixed-price brief reads the brief literally. The brief was wrong. They are technically not. You wear the variation.

An offshore team works to a spec you wrote at midnight in a panic. The spec is missing every assumption that lives only inside your head. You discover this in standup, three weeks in.

ChatGPT writes a function that compiles, runs, and looks plausible. It also confidently imports a library that does not exist. You waste an afternoon proving it to yourself.

Claude Code, on a good day, writes a feature in twenty minutes that would have taken me two days. On a less good day, it solves a problem I did not have, because the prompt I gave it was a paragraph instead of a page.

Different workers, different failure modes, the same underlying story. The faster the worker, the more expensive the missing page becomes. With a graduate dev you get a fortnight of rework. With an agent you get the rework before lunch.

And then they leave.

The graduate dev gets promoted. The contractor’s engagement ends. The offshore team rotates. The agent’s session expires. The why goes with them, into Slack threads that auto-archive, into commit messages that say, “fix login,” into Confluence pages last edited eighteen months ago, into standup conversations nobody recorded. Six months later, or two years later, you cannot answer the question “why did we build it this way?” Not won’t. Cannot. The institution itself has forgotten.

That is two failures, not one. Specification is the immediate failure: vague requirements in, wrong code out. Why-loss is the compounding failure: even when the requirements were right, they do not survive the worker who wrote them. Both have the same fix. Keep the requirement next to the code, in a form that outlives the tools and the people who made it.

If the requirement is the expensive part, and the requirement is what gets lost, the requirement is what’s worth keeping.

I started keeping mine. Not in Word documents on shared drives, those rot. Not in JIRA, too heavy for a one-person team. Just markdown files in a git repo, sitting next to the code. One file per idea. A clarifying note when someone asked the right question. A plan when it was time to commit. A test that proved the plan worked. A defect when something didn’t.

After a while you notice the files are connected. The clarifying note answers the idea. The plan implements the requirement. The test covers the plan. The defect points at the broken plan, or the broken code, or, often, the broken assumption you wrote down on the page six months earlier and then forgot.

That set of files (idea, requirement, plan, test, defect) is the same set whether the work is happening in 2008 or 2026, whether the worker is a junior dev, an offshore team, a contractor, an agent, or a product owner and three of the above on the same artefact. The shape of the work does not depend on the worker. The shape is the work, and the shape is what carries the why.

So, I wrote the shape down.

I did not build this when I had a team. I built it when two things happened at once. The agent in the other window finally got fast enough that the robot was finishing while I was still typing the brief. And the surrounding tools kept getting more numerous and more siloed, so the brief itself was still in a different system from the code, the test, and the eventual defect.

This is kaos-control (working name, might change). It is a single binary you run on your laptop. Point it at a directory of markdown files and it gives you a graph view, a markdown editor, and an agent runner.

The directory is the source of truth. The graph is a visualisation. Every file has YAML frontmatter that says what it is (idea, requirement, plan-backend, plan-frontend, plan-test, defect) and what state it is in (draft, clarifying, planning, in-development, in-qa, approved, done).

The product owner and the developer are not working in different tools. They are working on different artefacts in the same lineage, in the same directory, under the same rules about what gets approved by whom before it can move forward. When the product owner clarifies a requirement, the file appears next to the idea that prompted it. When the developer implements a plan, the commit lands next to the plan it implemented. The why and the what stay in the same place.

Every file in a chain shares a slug and a monotonic index. The originating idea is login.md. The clarified requirement is login-2.md. The backend plan is login-3-be.md, the frontend plan login-4-fe.md, the test plan login-5-test.md. Hand someone the slug login and they can read the entire history of how that feature came to be, in order or out of order, with the rejected attempts still visible in git.

A workflow state machine governs the transitions, declared per-project in a YAML config. A planning artefact only becomes in-development once the backend, frontend, and test plans are all approved. The product owner can override anything, because in real projects somebody always has to.

When an artefact is ready for the next step, you press a button. An agent runs as a subprocess against the project directory, writes its output as the next file in the lineage, and commits it to git with an attribution like agent(analyst): run a3f9d… [done]. You read what it produced. You approve it, or you reject it with a comment that itself becomes a child artefact you can refer to later.

I built kaos-control by using kaos-control. The screenshots above are real artefacts from this project’s own lineage. If you wanted to know why the frontend is Vue 3 instead of React, the answer is not in my head or in a Slack message. It is in the requirements file; with the alternatives I considered and rejected. Six months from now, when I have forgotten, the file will still know.

Here is the part it took me a while to notice.

The requirement survives the worker. Once you accept that, the worker becomes a configuration choice, not the centre of the design.

Capturing ideas on a train? Open the editor, write a one-line idea, commit. Do not run an agent at all. The idea sits in the directory until you have time and tokens to take it forward.

Solo dev with a Claude subscription? Run an agent at each step, review every artefact yourself, ship at your own pace.

A real team, with a product owner, two developers, a tester, and maybe an agent or two? Map the roles to people. The same gates that stop a half-baked agent run from going into development stop a half-baked human PR from doing the same. The product owner approves requirements. The developer approves plans. The tester approves the test plan. None of them write in a different tool from the others. The backlog grows; the shape stays.

The framework does not push you toward the AI-factory model where you fire prompts at agents around the clock and hope something useful falls out. It lets you decide how much robot you want, when, and for what. Some weeks I run no agents and the directory still works. Some weeks I run six in a morning, and the lineage still tells me what happened, and why.

The requirement is the constant. Everything else, including the robots, is optional.

Vibe coding will keep being a useful trick for the first week of a project. After that you need a way to remember why. The robots are not going to do it for you. They have already moved on.

Thirteen years on, opEvents is still doing its boring useful thing inside organisations like Microsoft and NASA. I do not remember the code. I do remember the PowerPoint.

I made a tool to keep the artefacts.

kaos-control will be released soon. Any suggestions on a different name?

Active development, single binary, bring your own Claude, local or cloud LLM.

If you have ever opened a vibe-coded project six months later and asked yourself “why does it work this way?”, this is the tool I built so I would not have to wonder again.

If you’re interested in trying it out, or have ideas on a better name, get in touch.

Share

Leave a comment

No posts

Read the original on kcsinclair42.substack.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.