Return of the Spec

Agentic development is bringing a resurgence of "the specification". Maybe you've been writing detailed specs all along, but I've been mostly following Working software over comprehensive documentation. To some it'll sound like I'm some combination of crazy and lazy but historically I have not found heavy specs to be worth the time or effort for a number of reasons I'll get into later. Agentic development is forcing me to take a second look though. Here's why:

Here's what changed

They're easier to write now

Long, detailed specs are cheaper and easier to write now, changing the ROI calculation dramatically. You can have an agent write them for the most part and you can just check them for correctness. I'll talk about how later in this post.

They're better informed

The agent is also capable of understanding complex codebases much faster than I ever could and so the specs can be made much more quickly and can take a lot of the complexity of the codebase into consideration better in advance. When trying to add a complex feature to a complex codebase I used to just start chipping away without much investigation (e.g., I'd start by just writing a failing test, even though I couldn't remember how the code was implemented at all), but now the agents can understand the codebase in a few moments, and be able to help you write a much more informed spec up front.

They take the human out of the loop for longer

But the most important advantage of a detailed spec now (and the actual reason for the resurgence) is that it can be used as a detailed prompt.

When the spec is really nailed down, you can sometimes set a /goal to satisfy the spec, let an agent spin up whatever subagents it needs, and let it run until the work is done. This frees you up to do other things.

While this is the most valuable part, I want to be clear about the rationale: The goal is not fewer human decisions; it’s fewer low-value interruptions. You still want human judgment where it's actually necessary.

Why it wasn't worth it before

Isn't this just waterfall again?

There are 3 aspects of the spec that have traditionally been pretty waterfally:

The spec will invariably be wrong

The spec will invariably be wrong (either incompatible with the existing product/codebase, or not actually the best solution for the user/business) in some ways that we can't foresee. Sometimes it will be disastrously wrong. You just can't know everything in advance. We need to be iterative.

In my experience, agents that have access to the codebase can find many problems/questions/concerns with a plan that I hadn't thought about in advance. This allows the agents to be a tool for writing specs that are "less wrong" than specs I would have written on my own before agents existed.

Spending a long time on a specification doc is spending a long time without delivering actual solutions to user problems.

This is still true, but I think we have the tooling now to write good comprehensive specs really quickly. I hope I can prove that later.

Larger specs create larger batches and will create more problems downstream for reviewing and merging.

When you create a large spec, you can (and probably should) break it up into thin vertical slices for delivery. You don't need to get out of the feedback loop of a large plan; you can stay in that loop and verify whatever you want. A large spec doesn't need to change how you deliver things. It could actually include your delivery and validation plan, e.g., the actual slices, validation points, and stop conditions.

I always recommend delivering the most uncertain parts first when possible (even if just as a limited availability prototype), so if your plan turns out to be a bad one, you learn earlier rather than later.

Unlike in waterfall, these specs can and should be revisited whenever. They're not contracts. They don't promise to guarantee business or user success just by correct implementation. They're still not as valuable as working code. We still want to learn (and iterate) while building.

I still just delete them after implementation

In general I don't care about keeping specs around as documentation; they're meant only to be used for prompting in a short-term way. The codebase isn't necessarily documentation-free; for example I like ADRs for example to explain WHY I made certain decisions ("Why?" is a question that code rarely answers well).

There's still not really anything to force natural language specs to be in-sync with the actual behavior of the codebase in a deterministic way that I would trust so with few exceptions I just throw the specs away after. The spec is scaffolding: useful while building, but disposable once tests and code guarantee the behavior. I don't want a chance that an agent could later read an incorrect spec when it can just read the tests or the code. (It's worth noting that there are tools like speckit that are trying to bridge that gap)

Maybe I'll change my mind on this later, but I haven't yet. With generating specs from existing code being so easy, I just haven't seen a need and I want to keep things as simple as possible. For now, a spec in plain English is disposable as soon as its behavior exists in automated tests and code.

I'm also not at all suggesting you make the specification a shared artifact in your organization. I'm using it to agree on the details between the agent and me. It's not something that anyone else will review or approve.

How to write good specs easily

Obviously we should use agents to help write the specs and I wanted to figure out how to do that with the least amount of human-entered keystrokes as possible. The best prior art for that IMO that I've found is Matt Pocock's grill-me-with-docs skill. You give it some tiny, massively under-defined description of what you're trying to do, and it asks you questions relentlessly to get a clear picture of what you want (along with near-instant understanding of the existing code) that it can document into a clear plan. It's absolutely amazing for spec writing.

I made a few tweaks though so answering was also faster and easier. I wanted it to...

  1. ...suggest possible answers so that the questions would be multiple choice (including an "Other" escape hatch for a plain text answer of course).

  2. ...assign each possible answer a "certainty percent" chance that it thought the answer was correct so it could mark the highest confidence one as "Recommended". That made it so I could easily scan for the recommended answer and select it without reading the others if I liked it.

  3. ...actually stop itself from asking questions when all its remaining questions had a certainty percentage higher than 75%. Pocock's skill will just grill you until you give up.

Here's how it looks in practice:

› $plan-questions add github authentication


• I’ll use plan-questions for this. I’m going to inspect the existing auth/domain docs first so I only ask questions that
  aren’t already answered by the codebase.

• Current backend already has Better Auth social providers for Google and Apple, and the web login has a Google button. I’m
  checking mobile auth and environment/schema details next, because “GitHub authentication” could mean web-only, all clients,
  or just provider configuration.

• The code points to a generic OAuth launch path on iOS/Android, which reduces the provider-specific work. I’m reading the UI
  entry points so I can separate simple button/provider additions from deeper account policy questions.

• I’ve got enough to start grilling. One notable code fact: Android’s callback spec explicitly calls the flow “Google sign-
  in,” but the callback plumbing is generic OAuth; if we add another provider, some domain language should become “social
  sign-in” or “OAuth sign-in” rather than Google-specific.


• Question 1: Scope

  When you say “add GitHub authentication,” should GitHub be a supported social sign-in provider everywhere Winternote already
  exposes social auth, or only on web?

  A. All clients: web, iOS, and Android. Add GitHub beside Google on web and native OAuth surfaces, keep callback/token
  behavior shared. Recommended, 70% certainty because the repo treats auth as a cross-platform product surface and mobile
  already has generic OAuth plumbing.

  B. Web only for now. Add backend env/provider config and a web login button, leave mobile unchanged.

  C. Backend only. Configure Better Auth for GitHub but don’t expose UI yet.

  My recommendation is A, but I’m under the 75% threshold because GitHub sign-in may be less useful or awkward on mobile
  compared with Google/Apple.
  
> [ ]
  

I've got my iteration, /plan-questions here. Credit is primarily due to Mr. Pocock though for almost all the thinking here. I love how he's grounded it in domain-driven design to help you settle on terms for describing the type of work that you're doing. It really helps make communication between you and the agent (and the codebase) all the more clear.

I don't write specs for everything

I certainly don't use specs for everything. For defects for example I use my /undefect skill. A specification is just a tool you can use whenever you think is right.

For work that involves UI changes I will often additionally want to iterate on some kind of a mock-up of the UI changes as well, so I don't get a terrible UI on top of my detailed spec. A spec in English prose will rarely get those details right.

I do often call /plan-questions for tiny things though. Sometimes it has no questions, or sometimes it has just 1. It's a tiny payoff but it's also a tiny effort.


← Back home