Bower learns to adopt

Spec-driven development for the code you already have

I’ve written before about Bower, my little spec-driven-development (SDD) framework for building software with AI agents. Quick recap: Bower is a set of conventions (instructions, commands, subagents and processes) that focus on documentation and design as the engineer’s first-class output over code (the SDD manifesto). With it, your agent deeply plans before it builds, writes the design down as it goes, and refuses to let you quietly bolt a new module onto the side of the house at 11pm because you couldn’t be bothered opening the design command. → the repo

Why though? Well, there’s the software engineering principles argument which is something like this: AI makes it cheap to write code and expensive to write the wrong code. The central proposition is that you spend your productivity winnings on figuring out what to build, engaging with all the design decisions that matter and ensuring those are recorded. A repo with high quality SDD docs is a better long-term investment than one with a few more lines of code.

I’ll add another framing though. Engineering in the new AI world order often means flipping between several projects which are underway concurrently, e.g. we’re waiting for an agent to finish, we’re not sitting around twiddling our thumbs, we jump to something else and work on that. Smarter people than me can probably work out how to do that on the same project, but in my little research software engineering world, it makes most sense to jump to a completely different project. Now my headspace needs to be able to hold the context of several projects at once, and frankly I’m finding it a pain in the arse! Let’s say the effect is that the chair-keyboard meat (us) now has incomplete context for these projects, and the same is true when we return to old projects. We see what needs doing, and we write out a prompt and since we’re engineers, it’s not “make output better” it’s a description of how to effect the change. But the problem is that we don’t remember why we made the decisions we did, and the AI doesn’t know either. It’ll just act on whatever thought bubble we blurt into the console.

What I want is for my robobuddy to say, “well now hold your horses there cowboy, that’s a bad idea. Go get a coffee while I explain why.” That’s the sci-fi promise of an assistant that remembers what I can’t. It’s achievable, the trick is to capture the why up front: not just our why, though that’s the key bit, but the agent’s why too. Because if you haven’t yet twigged that a well-briefed agent often makes better calls than we do, you will.

Agents forget too, and it’s more brutal than our forgetting. One /clear and the last hour of their thinking is summarily jettisoned. We don’t want an agent spidering the whole codebase every time just to work out what it already did. The trickiest thing in harness design is really the access graph: arranging things so an agent can bootstrap fast, loading precisely what it needs and nothing it doesn’t. In practice that’s indexes, mostly, and a lifecycle of process docs.

But all of this leans on one thing: that the why got captured while someone still knew it. That’s easy enough when you start a project this way. When the code came first and the why is already long gone, that’s a much harder problem, and one I’ll come back to.

There are other SDD frameworks and I make no claims this is universally better! I looked at a number of them (as in actually tried them out) and mined them for good ideas, so this stands on the shoulders of giants. Bower is tailored for the small team engineering (1-3 typically) with a focus on sustainability and performance.

Let’s also be up front and say that if you understand what problems this solves, you can write a paragraph to your agent establishing a spec and plan regimen which will serve projects fine. That said, Bower is somewhat richer, and has some moderately fancy design, modularisation, integration testing, review subagents, and a few other things get you further when your project is larger. You could also write your own framework and nick any good ideas out of this. None of this is a secret, in fact I’d argue this is the kind of stuff today’s engineer needs to know more than the foibles of the latest JavaScript framework.

If you want the long version of why it’s shaped the way it is, the rationale doc lays it out. → why Bower works this way

The gap: what about the code that already exists?

Bower was developed with greenfield projects because in my world, there’s always a bunch of them and it’s easier to shake out how it should work. Most software isn’t greenfield though, it’s a pile of code somebody wrote two years ago that now needs looking after, and telling a framework “just design it forward from intent” is useless when code is all you have, and that only tells you what it does and rarely why.

That’s the hard bit about adopting any spec-driven framework onto an existing project. You can’t reverse-engineer the reasoning. The temptation is to have the AI read the code and invent a plausible backstory but that’s the trap because the SDD contract says our docs are authoritative.

v0.21: /b-adopt

So 0.21 adds /b-adopt, and after giving it some thought, the solution is a design where we tackle uncertainty up front and work through that uncertainty over time until we work through the deficit in documentation. Initially, /b-adopt surveys your existing codebase, reconstructs the orienting docs including scope, architecture, module boundaries, an initial conventions file and marks everything honestly as “as-built, not verified” rather than ticking it off as done.

We achieve this through an adoption ledger. Every cross-cutting choice it finds in your code but can’t explain gets written down as a one-line open question appended to a worklist of sorts. And it only ever shrinks: you either capture the real reasoning, fix the thing if it was a mistake, or shrug and delete the line. When the ledger’s empty, the “this was reconstructed, handle with care” banner comes off and the project’s just a normal Bower project. The whole provisional-ness lives in one place and then evaporates. Greenfield projects never pay a cent for any of it.

I’ve shipped it as a v1. It was tested in older repos of mine, to the extent that I judged the docs and adoption ledger to be sufficient. It’ll almost certainly change once I have occasion to work on an adopted codebase and find the edge cases. The full changelog and the design reasoning are on GitHub. → v0.21 notes

  • #Bower
  • #spec-driven development
  • #AI agents

← all meatspace posts