Work AI

Build Wide, Ship Narrow

Bruno Quaresma

Bruno Quaresma

Product Engineer

Good engineers plan before they build. The workflow I grew up seeing: write an RFC describing the feature, split it into smaller issues, then build them, each issue often blocking the next. The structure of the work was locked in before a single line of code existed.

This is reasonable. It keeps code reviews manageable and avoids big-bang merges. It also asks you to make your most critical structural decisions at the moment you know the least about the problem.

Before you've built anything, you're guessing: which pieces are separable, how complex each one will be, whether step 3 will force you to rethink step 1. Sometimes you're right. Often you're not, and step 1 gets thrown away. You learned something building it, but you'd have learned it faster by building the whole thing first.

We paid that cost for a good reason: the alternative was building everything and untangling it by hand, and untangling a week of work is harder than planning ahead. Deciding boundaries up front was never about making the build easier. It was about making review possible, and it was the only affordable way to get there. That's the part that changed.

What changed

Three things got dramatically cheaper. Building: an AI assistant turns a clear problem into working code in hours, sometimes minutes. Design: you can interrogate a plan and reshape it at conversation speed. And the one that matters most here, decomposing a finished branch: splitting a week of tangled work into a sequence of small PRs used to be the most tedious part of the job, which is exactly why we avoided it. It's now a prompt.

Two things didn't get cheaper. The first is the judgment half of code review. Agents made the mechanical half (consistency, nits, obvious bugs) nearly free, but they don't settle subtle correctness or the questions around it: does this change belong where it is, will this endpoint shape hurt six months from now. A bot approving your PR isn't the same as you understanding the code, and if you didn't type the code, reading it is how you come to own it. Narrow PRs make that reading possible.

The second is product validation. Running the thing and deciding it's the right thing to build is still slow. What's new is having the whole feature working early enough to show someone before anyone reads a line of it.

So stop pre-deciding boundaries to dodge a cost that no longer exists.

My workflow now looks like this:

  1. Grill the plan until it has real decisions in it
  2. Commit the spec before any code, when the design is novel
  3. Build wide, committing save points as you go
  4. Demo and iterate before anyone reads the code
  5. Split into PRs along the boundaries the code revealed
  6. Merge, cleanup last: pure deletion in its own final PR

Design still goes first

To be clear: this isn't "skip planning and start coding." Before I touch the editor, I have a plan, and every feature starts with an interrogation. I run grill-me, a skill that interviews you about your idea in adversarial rounds until it has real decisions in it. What's the fallback if the API call fails? I run it on everything, including small changes, and it keeps surfacing gaps I didn't know were there.

When the design is novel, the plan becomes a spec committed before any code. On a different project, the first PR was a document: what the feature was, how it would work, where the trust boundaries sat. It merged days before any implementation existed, so the team could push back first.

What never gets committed is a decomposition into PRs. Decide what to build before you build it; decide how to slice it after.

Build wide

A crumpled scratch-paper build branch on one side and a clean fan of five pull requests on the other

Once the design is settled, I build. I often work in steps, but I don't stop at each one to open a PR and wait for review. Everything stays on one branch until it works end to end, across whatever files are in the way.

Commits happen, but they aren't milestones for anyone else. They're save points: a concept is proven, or I'm about to try something risky and want a rope to pull back to. A refactor I finished recently ran to a dozen-plus commits in a single day across dozens of files, with operational messages. Waypoints so I can see where I've been, not a story for a reviewer.

This is the part that makes some engineers uncomfortable, and I understand why: git history is supposed to be the record. But this history never becomes the record. The PRs at the end are cut fresh off main, and the build branch is scratch paper you throw away. Two audiences separated in time, me and the reviewers, and keeping them apart lets you optimize for both.

Demo before anyone reads the code

Once the work is in a good place, I stop and show it. Not as a PR or a code review, but a short video in Slack, or a preview deployment if the change needs clicking. Feedback on working software from the people who will use it, before a single code review starts.

Review is expensive now that the cheap half is automated. Finding out at review time that you built the wrong thing (confusing UI pattern, an endpoint shape that doesn't fit how the frontend uses the data) burns a reviewer's time and your own. A demo catches it while changes are cheap. If it surfaces something that needs rethinking, I run grill-me on the feedback first, so the iteration isn't just vibes.

Ship narrow

One tangled build branch cut into five narrow pull requests, with the deletion PR last

The build order is only a rough draft of the split: the steps get regrouped and re-cut. The deletion PR is the clearest example, a unit that only exists at the end, once the new path is in place.

I run one prompt:

Split the current work into the smallest set of independently reviewable PRs, each safe to merge on its own, and each delivering value to the user whenever the work allows. Create a git worktree and branch off main for each. Stack only where a dependency is real; otherwise branch from main. Any removal of the code being replaced goes in its own final PR. Show me the proposed split before creating anything.

How long it takes depends on how tangled the work is, from a few minutes to a few rounds of back-and-forth. Either way, no manual cherry-picking.

That refactor came out as five PRs: two backend endpoints as siblings off main, two frontend views each sitting on top of the backend PR whose data it needs, and a final PR that was pure deletion of the old path. The deletion removed several hundred more lines than the whole feature added. That's the shape of a refactor done in this order.

Two rules I've arrived at by doing this repeatedly:

Stack only when the dependency is real. A frontend view PR depends on its backend endpoint PR, and the branch reflects that. Everything else comes from main. Stacking for convenience creates a rebase chain you'll regret the moment the bottom PR gets feedback.

Cleanup ships last. The old code dies in its own PR, after the new path is live. Mixing deletion with creation confuses reviewers, makes rollback ambiguous, and buries the cleanup in the noise of the feature.

The split is also when I read my own work. Going through the diff PR by PR, at a size I can hold in my head, is the difference between having shipped AI-written code and understanding it. I'd rather find my own problems there.

One practical note: managing a stack burns context fast, so hand the split work to subagents that report back to a main agent. In Cursor, the split-to-prs skill packages this.

What it bought, what it costs

The heavy PRs stay heavy, and they should. The backend ones carried the real architectural risk (new data models, new API surface, trust boundaries), which is where reviewers should spend their attention. The frontend PRs that consume them read in minutes. Small, focused PRs flow. Large ones sit.

The agent review loop is faster at this scale too. At Adapt, we use Adapt itself as a reviewer, an agent with business context from previous work. It comments within minutes of a PR opening, and the exchange (questions, clarifications, a small fix) resolves in under ten. That only works when a PR is small enough to read quickly; a 2,000-line PR mixing several concerns doesn't get that treatment from a human at all.

Merging incrementally also makes deployments easier to manage. If something breaks, you revert one focused change, and your error tracking points at that change instead of an entire merged stack.

Those are the gains. Two costs come with them.

Rebasing. When a reviewer asks for a change on a PR that another sits on, every branch above it needs rebasing. It doesn't happen often, since reviewers usually touch leaf PRs, but when it does you feel it. Keep the chat session that produced the split open: it still holds the split, so you can re-prompt it to update the branches above instead of doing it by hand.

Splitting is not shipping. As I write this, all five PRs from that refactor are still open. A good split makes each PR easy to review and worth merging on its own. An agent does the first for me; the second is my call when I decide what goes in each PR, and my team's when they decide what to merge. Mine sat because I only did the first. Even if all five merge on the same day I keep the review benefit and a clean revert target per change; what I lose is incremental delivery, since nothing reached a user earlier and the deploys land as one batch.

When to reach for it

Good fit: multi-surface features crossing backend and frontend, refactors where you don't know the final shape until you've done it, any work where you'd otherwise be guessing at issue boundaries.

Harder fit: migrations and schema changes that must be sequenced in production, where the ordering is real and you should plan it first. Work that has one obvious place to cut. Features where step 1 cannot ship alone, ever; if everything lands at once, late decomposition buys you incremental review and nothing more.

The heuristic: if you're writing an RFC and guessing at how to break it into issues before you've built anything, that time is probably better spent building. You'll have better answers at the end. I've been testing this across a few projects and it has held up.

The structural decision doesn't go away. It just gets much cheaper when you make it with the code already in front of you.

About the Author

Bruno Quaresma

Bruno Quaresma

Product Engineer at Adapt, building the product and experimenting with AI-native development workflows.

Bring the integrated coworker to your whole team. Get started free with $100 in credits when you add Adapt to Slack.