On 2026-04-27 I committed a 277-line build plan for a content editor. I never edited it again. The editor got built. It runs today on ByteMD, R2 and Cloudflare Access, exactly as the plan said, and it also ships translation, revision history and a health endpoint, none of which appear in the plan even once. It does not use Preact, which the plan names four times.
Nothing about that is unusual. What changed is that I stopped writing the plan.
The loop I used to run
The old loop was four steps, and for a year it was the only one I had.
It is the shape GitHub’s Spec Kit formalised, the one IBM and Microsoft now write up as spec-driven development, and it is a genuinely reasonable answer to the question every agent forces on you: what exactly am I asking for. The agent needs scope. A document is scope. That much holds.
Here is what did not hold, on my work, once the agent was the thing doing the building.
The four things that broke
1. The plan was missing scope before anything started
docs/editor-plan.md covers architecture, roles, seven views, storage bindings, a permissions
table. It is not a lazy document. And the three surfaces that turned out to matter most were
invisible to it, because they had not happened yet:
| Term | Times in the plan | Shipped |
|---|---|---|
| ByteMD | 5 | yes |
| Preact | 4 | no |
translate | 0 | yes |
revisions | 0 | yes |
health | 0 | yes |
Translation is the one that stings. The editor’s translation endpoint now sits next to a whole
class of problems I could not have named in April. In August one of them became its own piece of
work: vpn#482, “Translated pages run months-old
versions of the hubs.” A plan written before the site had 16 languages cannot warn you about that.
That is not a flaw in the writing. It is what a document written first is.
2. It was wrong within weeks and nothing told me
Preact appears four times. The shipped editor is a single 4,942-line static/index.html with no
framework at all. Somewhere between April and now I made that call, and I made it in a terminal,
and the plan kept saying Preact.
An agent reading that plan has no way to know. It is a confident, well-structured, internally consistent document, and it is wrong in a specific place. This is the same failure I wrote up in AI trusts your docs, and that’s the problem: hand a model bad ground truth and it will validate the bad ground truth, thoroughly and fast.
You can defend against it. You instruct the agent to re-verify every claim in the document before acting on it. I did that for a while. It works, and it means every task now starts with a research phase that re-derives things you already knew, which is slow and which you pay for on every single run.
A markdown plan: one file, no state, no owner, no closing condition. Wrong in a way that reads exactly like being right.
An issue: has a state, an owner, a parent, a close event, and a comment thread where the correction lives next to the claim.
3. No track record
Ask me what markdown-planned work I finished in April and I have to go and read files. The plan
does not know it is done. editor-plan.md is sitting in docs/ right now, in the present tense,
telling any agent that opens it that the editor will be built in Preact.
Multiply that by every project. Three months of finished work leaves behind a folder of documents that all still sound like proposals.
4. Digging through documents is not a search
This is the least interesting failure and the one I hit most often. A board answers “what shipped last week” and “what is blocked” in one click. A folder of markdown answers neither without reading.
Those four are what the format cost me. Here is the same list against what an issue does instead:
| What broke | What an issue tree does instead |
|---|---|
| Scope missing before work starts | Scope is added as sub-issues when the work reveals it, without invalidating the parent |
| Stale and confidently wrong | Corrections land as comments on the claim, and the issue’s state changes with reality |
| No track record | Closed is a fact with a date and an author, not a judgement about a file |
| Not searchable | Filters on label, state, parent and text, from the CLI or the board |
What I replaced it with
GitHub issues, in trees. Not a new tool, and that is most of the appeal.
Take vpn#482 as the counterpart to the editor
plan. Opened 2026-08-12. Four named sub-issues:
/vpn/ to parity across every languageAll four closed. The parent closed on 2026-08-14 with four comments on it. Two days, and the record of what was decided sits on the thing that was decided about.
Four properties matter, and only the first is about writing:
What I ask of an issue tree
Do
- The parent states the problem, not the solution. Sub-issues hold the solution and can be wrong.
- One sub-issue is one agent’s worth of work, scoped so two agents never touch the same files.
- Closing requires a comment with the command and its output, not the word “done”.
- Sub-issues get added mid-flight. A tree that only shrinks was scoped as a document.
The second one is the one that took me longest to internalise, and it exists because of worktrees. Agents work in parallel now. A task scoped as prose (“improve the translation pipeline”) cannot be handed to one worktree safely. A task scoped as a sub-issue with named files can. The issue tree is not just a record, it is the thing that makes the parallelism safe.
Sub-issues are a real GitHub primitive, not a convention I invented, which matters because it means the parent/child link is in the REST API and an agent can walk it.
What four boards look like 24 days in
I started this on 2026-07-27. Everything below was read live from the GitHub REST API on
2026-08-20 and written to docs/content/seeds/board-receipts-2026-08-20.json before this post was
drafted, because a piece arguing for a track record that cannot show one is doing the exact thing
it complains about.
| Board | Issues | Open | Closed | Parents | Sub-issues | agentic |
|---|---|---|---|---|---|---|
| vpn-astro | 621 | 360 | 261 | 90 | 463 | 77 |
| uxxray | 409 | 132 | 277 | 37 | 212 | 38 |
| askbowtie | 103 | 26 | 77 | 9 | 40 | 11 |
| launchwithben | 45 | 20 | 25 | 5 | 24 | 16 |
| Total | 1,178 | 538 | 640 | 141 | 739 | 142 |
The median tree is 4 sub-issues. The largest is 36. That is the granularity difference in one
number: the editor got one 277-line file, and
vpn#224 gets 36 individually closeable pieces.
Now the number that does not flatter me. 561 of the 640 closed issues carry at least one comment, which is 88% and sounds excellent. It is not the thing I actually want. I want closures that carry evidence: the command, the output, the URL. So I sampled 60 closed issues, spread evenly across the four boards, and read the comments.
Twenty-eight percent. The format made a record possible and did not make me disciplined. That is worth saying plainly, because the honest version of “I switched to issues” is that the structure holds and the standard on top of it still has to be enforced, the way anything else gets enforced around here: audit it before it spreads.
On “AI project management tools”
If you search for a way to manage what your agents are doing, you get product listicles. Atlassian, Planner, a dozen vendors with an AI badge on a Kanban board.
The contrarian answer is the boring one. Your agents already understand git and they already
understand issues, because both are in their training data and both have a stable API. There is no
adapter to write, no schema to teach, no MCP server to keep alive. gh issue list --label agentic
works from any session, in any repo, at no cost. I run 142 agentic-labelled issues across four
boards on exactly that, and the entire tooling budget is a folder of shell scripts.
I am not claiming the vendors are useless. I am claiming that for a solo operator whose workers are coding agents, the thing you would buy is a worse fit than the thing you already have.
Where a spec still wins
Two cases, and I want to concede them properly rather than wave at them.
Greenfield, before a codebase exists. There is nothing to grep. There are no consumers to check. A document is the only artifact available, and writing one is the correct move. The editor plan was a good document. Its architecture section was right, and the editor was built on it.
A team that needs shared intent. I cannot speak to this at all. My boards are one operator’s, and the strongest argument for spec-driven development is several people agreeing on a target before anyone writes code. Nothing in my numbers touches that, and I would not trust anyone who told you otherwise from a sample of one.
I also do not think the failure I am describing is exotic. Augment Code, Isoform and Arcturus Labs have all made the drift argument. What none of them publish, and what I have tried to put in this post, is a plan you can open and a board you can count.
What this does not cover
There is also no control. I did not run a markdown arm beside an issue arm on the same work, so
none of this isolates the format from everything else that changed at the same time. And the boards
are private, so what I can publish is the counts and the method, not a screenshot. Every figure
above is reproducible with gh api --paginate repos/OWNER/REPO/issues?state=all, which is the
whole point of putting them in a committed file.
Sources
- Spec-driven development, Wikipedia
- GitHub Spec Kit and its announcement
- Adding sub-issues, GitHub Docs
- Issues REST API, GitHub Docs
- Board figures:
docs/content/seeds/board-receipts-2026-08-20.json, read live 2026-08-20
Related:
- Claude Code Worktrees: 4 Gaps in the Default Setup: why sub-issues have to be scoped to files, not outcomes
- AI Trusts Your Docs. That’s the Problem.: what happens when the stale plan is the ground truth
- Audit Before You Spread the Mess: the enforcement half, which the issue format does not give you for free