All you need is more thorough planning

Mara Ellison
Mara Ellison June 26, 2026 · 7 min read
Bar chart: first-pass acceptance, no plan 4 of 8 versus plan first 8 of 8.

We're a small group of engineers, and coding agents are part of how we work most days. This is a writeup of something we kept getting burned by, and the little experiment we ran to check whether we were fooling ourselves about the fix. Short version: the fix is planning first, and when we actually measured it, it held up.

The first draft always looks done

The thing that kept catching us out was rarely the agent being obviously wrong. Sometimes the output was confidently, plausibly almost right. Sometimes it was quietly vague or ambiguous in a spot we didn't notice. And often it just looked good enough — clean implementation, green tests, reads fine in review — that we couldn't put a finger on any one line and say “that's the problem.” Then a week later the numbers don't reconcile. Two coupons that should have summed to 30% off had quietly compounded to 28%. A promo code pushed an order total below zero. Sales tax came out of the pre-discount price.

Nobody introduced a bug. The code does exactly what it says. The problem was that our prompt left a dozen small decisions unstated, and the agent — reasonably — picked one for each and kept typing. It never stops to ask; it fills the gap with the most obvious choice and moves on. And the most obvious choice is rarely the one we'd have made if anyone had actually put the question to us.

The other half of the problem is where you'd catch this. Even when we could feel that something needed nailing down, a coding agent's chat window fought us: it's a single thread, one point at a time, scrolling away as the agent keeps going. But a real task doesn't have one open question — it has a dozen, and they're tangled together, where the rounding rule bears on the discount cap which changes what “total” even means for tax. Confirming all of them, in detail, at once, in a linear chat while code is already being written, is genuinely awkward. So most of the time we didn't; we let the small ones slide and hoped.

That's the real cost, and it isn't speed. The agent is fast; the problem is that fast and unasked drops you into a loop we know well — ship, break, reproduce, patch, re-review — and every silent guess is a round-trip we end up making later. We wanted to know how much of that we could avoid by just asking the questions first.

So we tried to measure it

We suspected planning-first was helping, but “it feels better” is exactly how a team talks itself into a ritual that doesn't actually pay off. So we set up something small enough to grade objectively.

We took a task every commerce team has written — a checkout pricing function: cart, stacked discounts, tax, a total in cents — and handed the same loose spec to the same agent twice. Once we let it build straight from the spec. Once we did what our developers and architects do by habit — reviewed the approach, revised it, and worked through the decisions the spec didn't pin down — and only then let it build. Then we graded both against eight requirements with an executable test suite: four mechanical (a cart totals up, a discount comes off, tax adds on, an empty cart is zero) and four that were the actual judgment calls.

Same prompt, same agent, same afternoon. The result is the one in the chart above: the unplanned build passed the four mechanical checks and missed all four judgment calls — 4 out of 8. The planned build got 8 out of 8. And the part that stuck with us is that each of those four misses is individually defensible:

None of these raise an error, and that's the whole problem: there's nothing to hand back and say “fix this.” The code runs and returns a number. It's just the wrong number, quietly, on every order that hits that path. The planned build got all eight, because the six decisions behind them existed before any code did.

The agent didn't get smarter between those two runs. It just stopped having to guess.

The gap is ambiguity, not intelligence

The lesson we took from this is that a better model wouldn't have closed the gap. A better model guesses more convincingly, which if anything makes the wrong decisions harder to catch in review. The information was never in the prompt. When you leave a decision unstated, the agent doesn't stop and ask — it takes the path of least resistance and keeps going. Multiply that across every ambiguous corner of a real feature and the first draft is a pile of confident assumptions wearing a green test suite.

Planning, for us, is just getting those decisions out of our heads and onto the page before a line is written. Not a heavyweight spec document nobody reads — a short, focused pass over the handful of things that are genuinely undecided.

What it looked like on real work

The pricing function is a toy, chosen because it grades cleanly. The reason we bothered measuring it is that we'd already been living the same story on real, production work. On the projects where we skipped straight to code, the agent kept producing something plausible that missed a decision we hadn't said out loud. A migration that had to run in a particular order. A pair of feature flags that had to move together. An auth edge case nobody had scoped. Each one was a reasonable first draft that cost us an afternoon of debugging later.

It's not that our engineers weren't reviewing. Our developers and architects review, revise, and improve what an agent proposes as a matter of course — that's the job. But done in a chat window, or in our heads, that review only goes so deep. The decisions that actually bite are the ones buried a level or two down — the interactions between choices — and those are exactly the ones a shallow pass skips. We needed the review to reach the depth the hard decisions live at, and the usual tools didn't take us there.

Once we made planning-first the default — actually talking the open questions through with the agent before it wrote anything — our rough accounting put the overall time-to-done down by at least 30%.

≥ 30% faster
Our own estimate of the drop in overall time-to-done after we made planning-first the default — not from typing faster, but from the rework we stopped doing: fewer reversals, fewer “that's not what I meant” rounds, far less debugging of decisions we could have settled in a sentence.

That's the number we care about — not first-draft speed, but time to something actually correct. The planned path looks slower at the start and finishes well ahead, because you stop paying for the same mistake twice.

You can also see it in the issue tracker. We went back over a batch of our projects — deliberately picking ones of roughly the same size, so the rows compare like with like — and binned them by how many rounds we spent iterating on the plan before anyone wrote code, then counted the issues later filed against that first implementation:

Rounds iterating on the initial planAvg. issues later filed on the initial build
1–543.2
6–1032.1
11–2027.4
21–5022.9

The more we hashed out the plan up front, the fewer problems the build came back with — from north of forty issues down to the low twenties, close to half. The catch is obvious: those higher rows mean ten, twenty, fifty rounds of back-and-forth. Nobody does that in a chat window. Which is the whole reason the surface matters.

Why we ended up building a tool for it

What our own experience made unmistakable is that the details a coding agent can't lock in on the first attempt are exactly the details an interactive plan nails down. Reading a spec, the agent has to guess. Talking through a spec — pointing at a line, asking “what happens here?”, having it ask back “did you mean X or Y?” — turns the guesses into decisions, on the record, before they harden into code.

That interaction is the whole point, and it's why we built inplan the way we did: your coding agent drafts the plan and raises its open questions as inline comments — every open point at once, each anchored to the line it's about, instead of scrolling past in a single chat thread — and you answer them in place, like reviewing a pull request before it's a diff. Then it builds against something you've already signed off on.

Coding agents already ask clarifying questions — that part isn't new. What a chat can't do is let you pin a question to the exact spot it's about, or hold more than one of them open at once: it's a single channel, one point at a time, wait, the next. Anchored comments change both. The agent raises questions on a dozen points at once, each pinned to the line it belongs to; you answer them in any order, in a single pass that's far faster than typing them one at a time into a CLI; and it comes back with follow-ups only where they're still needed — round one might open clarifiers on three threads, round two narrows to the two that still aren't settled. That's the difference: not that the agent asks, but that the asking is precise, parallel, and can go several rounds deep without turning into a wall of chat. It's what makes the ten- and twenty-round reviews from the table above affordable instead of exhausting.

None of this is exotic; it's the old discipline of deciding the ambiguous things first. What changes is that it finally gets cheap enough to actually do — cheap enough that you plan and design thoroughly instead of bailing into the code before the hard questions are settled. With a coding agent, which will otherwise decide the unasked questions for you, silently, at full speed, that turned out to be the highest-leverage habit we've picked up.

Where the decisions end up

It's a toy example on purpose, but it's enough to show the difference that actually matters — and it isn't in the code. It's in where the decisions live. Take the same questions from the plan-first run, and look at the two ways of handling them:

Without a shared plan
plan.md — v1, sparse
“reject invalid URLs, dedupe the same one”
plan.md — regenerated
“coupons stack additively, cap at 100%”
plan.md — regenerated again
“tax on the discounted subtotal”
The reasoning is scattered through prompt history; the file only ever shows the latest overwrite. Ask “why is it additive?” in a month and the answer is gone.
With inplan
checkout-pricing.plan.md
Coupons stack additively, capped at 100%.
Q compound or additive? · A additive — “30% off” ✓
Tax is charged on the discounted subtotal.
Q before or after discounts? · A after ✓
Round half-up, once, on the final total.
Q per line or once? · A once, at the very end ✓
One file. Leave a whole batch of comments in one pass and the agent answers them in a single iteration — each anchored to the line it settled, and still there when someone asks later.

That last bit is what makes depth cheap. The answers come back in one regeneration, not ten serial replies, so going into far more detail costs almost nothing — you just leave more comments in the pass. And the difference compounds quietly over time: a CLI session is gone by next week, but the plan keeps the whole decision history, so “why did we do it this way?” still has an answer six months and three engineers later. The reasoning doesn't live in someone's scrollback — it lives on the line it applies to.

If this sounds familiar

inplan is the tool we built for exactly this — you and your coding agent settle the open questions inline before the code gets written. It's free and open source; the code's on GitHub if you want to see how it works or use it yourself.

inplan on GitHub inplan.ai
← All posts inplan.ai GitHub