strategy
The process I rewrote before it became the bottleneck
A release process built to let a dozen engineers share one codebase was the wrong shape now that writing code is no longer the hard part.
- Situation
- The department ran on a release process I had written years earlier, and it worked: merge request per feature, review and sign-off before merge, releases cut on a timed cadence. Management asked me to find out what GenAI did to that, and by the end of 2025 the answer was that we had made the first weeks of a project faster and the engineering needed clearer requirements before serious work could start.
- Constraint
- The gate that made a twelve-engineer release safe stood in front of a one-engineer prototype and charged the same toll. Removing it to keep up with the tooling meant giving up the thing the gate was there to protect, and keeping it meant giving up the only real advantage the tooling offered.
- Decision
- Split the lifecycle into three funded phases instead of tuning the gate. Discovery produces a functional prototype fast, with engineering consulted rather than staffed, and its only job is a working baseline the client can argue with. Engineering then takes that baseline under Mark Cerny's pre-production method and develops it into a finished demo, which is the artifact the estimate gets written against: a date the client signs against and a token budget the shop holds itself to, both measured on a real build rather than guessed. The final build is scoped for maintainability and the decade after launch, because by then the features are already settled. The rejected alternative was to keep the existing process and simply run it faster, which fails because the cost was structural rather than a matter of pace; the other rejected alternative, shipping the prototype as the product, is the race to the bottom, since a prototype that survives contact with a client is not maintainable by default and pretending otherwise moves the bill to the next cycle.
- Tradeoff
- A functional prototype looks finished to the person paying for it, so managing that expectation became part of the job rather than an afterthought. Engineers inherit code from a phase where velocity was the point, the audit that follows has to be scheduled as real work rather than absorbed, and a method that bills the first two phases has to survive a sales conversation that would rather quote the prototype and be done.
- Result
- Three phases, two of them funded and delivered before a line of production code is written, and an estimate that arrives as a date the client signs against and a token budget the shop holds itself to, rather than a range. The number the method has to answer for is the gap between the demo's measured burn rate and the final build's, because that gap is the whole bet.
What the old process was for
The process this replaced is its own case study: one engineer per project was the ceiling, and clearing it took a move to git, a merge request per feature, review and sign-off before anything merged, and releases tagged on a timed cadence instead of when someone declared them done. It took a department that struggled to put two engineers on a release and made twelve routine.
Every part of that was written against one constraint: many people, one codebase, and no safe way to know whose change broke what. The review gate is the load-bearing piece. It is what let a junior engineer touch a project at all, because the cost of being wrong was caught by someone before it reached a release.
That constraint did not go away. What changed is that it stopped applying to the whole lifecycle.
What GenAI actually changed
Management asked me to spend time with GenAI and report back on what it did to the way we worked. The department had been running the old process for years by then, and it was not in trouble; nobody was chasing a fix. We adopted the tooling at the end of 2025, and the process problem was visible before anyone went looking for it: a gate built for a twelve-engineer release was standing in the wrong place, and the tooling made that obvious the first week anyone had it in hand. The mandate was to find out what changed. What follows is what that finding turned into.
The honest version is narrower than the headline. Generation got cheap. The first working version of a thing, the part that used to be two weeks of scaffolding before anyone could react to it, became something one engineer could produce in days. That is genuinely good and it is not a small change.
What did not get cheap: review, integration, operating the thing once it is real, and deciding whether it should have been built. The cost moved rather than disappearing, and it moved later.
So the shape of the problem inverted. A process whose gate sat between a feature and a release was now sitting between a client and the first thing they could react to. On a twelve-engineer release that gate is the safeguard. On a one-engineer prototype, where the point of the artifact is to be wrong quickly in front of the person who can say it is wrong, the same gate is just the bottleneck. It was not that the process had become bad. It had become mispriced for the phase it was being applied to.
Discovery ends with something running
The change was to stop treating the prototype as a step before the project and start treating it as the deliverable of a phase with its own name.
Discovery now means working alongside the client to produce a near-production-ready functional prototype. Not a wireframe, not a clickthrough, and not a deck: something that runs, against their data, doing the thing they described. Scope and timeline get settled against that artifact. People react to working software very differently than they react to a description of working software, and most of what a discovery phase is really trying to buy is the correction that only arrives once somebody has used the thing.
That baseline does not go straight to a phase that audits it and calls it a product. It goes to a funded engineering phase whose only deliverable is a demo, and the final build gets scoped and priced only after that demo exists. The handoff between those two phases is the whole design of the method: the prototype is allowed to be fast because something downstream of it is under contract to slow down and make the thing durable. A third phase sitting quietly behind the first two is what keeps discovery honest, because nobody on either side of the table is pretending the prototype is the last stop.
The lineage here is Mark Cerny’s method for game production, which sets aside a funded pre-production phase whose output is a genuinely playable slice plus a schedule that can be believed, on the argument that you cannot estimate a thing you have not built. The same argument survives the move to enterprise software, and GenAI is what made the pre-production half cheap enough to run on engagements that could never have afforded it.
What the prototype is allowed to touch
Real client data, and only when it makes sense to use it. The point of the phase is a prototype the client watches behave in a real scenario and signs off on, and synthetic data hides exactly what that sign-off is supposed to surface: the records that do not conform, the volumes nobody mentioned, the field somebody has been repurposing for years. A prototype built on invented rows proves nothing except that the invented rows behaved.
Fast does not mean the security work gets skipped. The speed in this method comes from where the review gate sits in the lifecycle, not from suspending anything that has to be true in every phase regardless of what it is called. Secrets stay out of the repository and out of the generated code. Authentication runs on something battle-tested rather than whatever the generator wrote that afternoon. Access is scoped to exactly what the prototype needs to demonstrate, and where production data would be gratuitous the phase runs on a subset or on scrubbed records instead. A prototype is a smaller blast radius than a product, not a different rulebook.
That data decision belongs to the client’s own data owners, and it gets made before the phase starts, not discovered by an engineer mid-sprint. When that approval does not come, the phase runs on scrubbed data instead, and the sign-off at the end is worth less for it. That is a tradeoff made on purpose, not a surprise anyone gets to have later.
The demo is what gets estimated
The prototype crosses over carrying as little engineering polish as it could survive on, and that was deliberate: its job was a working baseline, not a foundation. Engineering takes it from there and does the work discovery was never staffed to do, and what comes back is a demo, a finished vertical slice built the way the real thing will be built. Finished means the parts a client will touch are wired to real services instead of fixtures, error states exist and are handled instead of skipped, and the slice runs under the same deployment and data access model the production system will use rather than a laptop-only stand-in. Anything short of that is a prototype wearing a demo’s name, and the estimate that follows inherits the lie.
The prototype proves the client wants it. The demo proves the team can build it, in this stack, against this data, at a rate that has now been observed instead of assumed. Cerny’s pre-production measures whether the mechanic is fun before a studio bets its budget on it. The measurement here is different: whether the architecture holds under real load, and what a unit of scope costs to build inside it once the scaffolding is real rather than borrowed. An estimate written against the prototype is a guess about a codebase that does not exist yet. An estimate written against the demo is a guess about how much of a codebase that already exists is still left to write.
It is not the prototype with tests bolted on afterward, and it is not a spike quietly promoted because it happened to work on the first try. Either one produces a slice that succeeds for reasons nobody can name, which is exactly the property an estimate cannot survive. If the demo cheats anywhere in that architecture, the estimate built on it is a guess wearing a number, and a guess wearing a number is worse than an honest range, because somebody is going to sign a contract against it.
A phase gate that has never rejected anything is not a gate. Sometimes the demo comes back and says the architecture does not hold under real load, or a unit of scope costs several times what the prototype implied, or the integration the whole design depends on does not exist in the form the client described. The finding is the deliverable in that case, not the failure. A demo that says no has done its job, and it has done it at the cost of one phase instead of the cost of a build.
Cerny’s analogy stops carrying here. A studio’s pre-production spends the studio’s own money to find out whether the game is fun, and the studio eats the loss when the answer is no. A consultancy runs the same phase on a client’s money against a contract, so a negative finding lands as a conversation about who pays for having learned it. The method only works if the first two phases are priced as deliverables that are allowed to conclude against the project, and that has to be settled in the contract before the phase starts, not argued afterward.
Tokens are a cost, not a line item
Token spend is not a line item on an invoice, and it was never meant to be one. It sits in the same column as electricity, laptops, and the office lease: real, tracked, and never itemized to a client. What earns it its own attention is that electricity does not spiral and token spend does. It climbs quietly, and it climbs fastest exactly when an engagement is going badly and somebody is re-prompting their way out of a problem they have not actually understood.
What the demo actually measures is a burn rate on work of a known shape, and that number is an internal control, not a quote. It tells the shop whether its margin survives the way this engagement is actually being built, and extrapolated against the remaining scope it turns into a budget the shop watches, so an overrun shows up in week three instead of at invoicing. The client still buys a scope and a date, the same as they always did.
None of this holds still. Model pricing moves under a running engagement, one part of a codebase burns tokens faster than another for reasons that only show up once you are inside it, and the demo is, by construction, the most tractable slice, built out of the part everyone already understood. The correction is a multiplier from demo to build, measured and then revised against the real burn as the phase runs, never trusted from the pitch alone. This is the same thing a shop has always done with hours, and rarely admits to.
A token has a price a vendor sets outside the room, which is genuinely better than a story point, a number a team invented and then re-argued at every retro. But the price was never the uncertain part. The quantity is, and remaining scope is still counted by the same people who used to count points, which means the multiplier is exactly where a lie would live if one were going to live anywhere. That is why it gets revised mid-phase instead of set once and trusted. A cost you can watch climb in real time against a baseline you actually measured is a control, not a crystal ball.
The third phase is the one that has to last
The final build is not where features get invented. By this point the features are already settled and the architecture has already run under real load. It is where the decisions that cost money in year three get made instead of deferred: what happens on call when something breaks, how the thing gets upgraded without a rewrite, who besides the person who wrote it is allowed to touch it, and what the team does the day the model that generated a third of the codebase is retired by its vendor. That last one has an answer and it is worth giving rather than raising: code does not depend on the model that wrote it. What depends on the model is anyone’s ability to regenerate a part instead of reading it, so the build phase is where generated code stops being something the team can re-roll and starts being something the team owns line by line. A dependency on a vendor’s model is a dependency you retire during the build by understanding what is there, and a codebase nobody has read is the only version of this problem that is actually fatal.
None of those decisions were free before GenAI and none of them are free now. What changed is that they get made in a phase that was funded to make them, instead of inherited by whoever is on call the first time one goes wrong.
Generation got cheap and ownership did not, and the three phases are built around that fact rather than around the calendar. The phase that used to consume most of a budget, writing the first version of the thing, is now the smallest of the three. The phase nobody used to fund at all, the one that decides whether the codebase survives its own second year, is where the risk actually lives now.
Why not just run the old process faster
Because the cost was structural. Shortening the review window or batching merge requests trims minutes off a gate whose problem was where it sat, not how long it took. Any version of that answer still puts a review boundary between a client and the first artifact they can react to.
The alternative at the other end, shipping the prototype itself, is the one the industry is actively taking, and it is worth being specific about why it loses. A prototype that a client has used is not the same object as a product. It has no operational story, its seams are wherever they landed, and the parts a generator wrote confidently are exactly the parts nobody has read. Shipping it does not remove the audit; it defers it to the first incident and charges interest. The audit phase is the price of being allowed to use the prototype as the spec, and it is cheaper than the alternative because it happens on a schedule rather than at 3am.
Where judgment comes from now
The old gate was doing two jobs at once. It kept bad code out, and it was also how judgment moved from the people who had it to the people who did not, because a junior’s merge request got read by someone who knew better before it went anywhere. Splitting the lifecycle keeps the first job, parked in the build phase where the review still happens. It does nothing for the second, and a method that does not replace it is quietly spending down the one asset the department actually compounds.
What replaces it has to be inverted by experience level, not handed out the same way to everyone. For an engineer with twenty years behind them the assistant is a force multiplier: they direct it, let it take the volume work, and spend their own attention on the auth flow and the cross-boundary refactor, the places it reliably produces confident nonsense. For someone mid-career it is a collaborator, and the risk is not wasted time but hidden debt, because a plausible decision made inside a gap in their knowledge looks exactly like a good one from where they are standing. For someone new the relationship inverts completely: the assistant is a tutor that occasionally writes code, the loop is understand, attempt, compare, learn, and it runs slower than the old way by a large multiple on purpose.
This belongs here and not in a training plan because the failure mode is a process failure, not a skills gap. At the junior end the danger is not bad code, it is an engineer who has shipped a great deal and learned nothing while believing the opposite, and that failure stays invisible for a year and then becomes permanent. Volume is no longer evidence of anything, so the thing the old gate did by accident now has to be scheduled on purpose: which phase a junior works in, what they can be asked to explain about what they produced, and who sits down and reads it with them.
What it cost
A functional prototype looks finished. That is the point of it and it is also the problem: the person paying has now seen something that works, and the months that follow can read as a bill for something they already have. Setting that expectation explicitly, before the prototype exists, became part of the method rather than a conversation to have later.
Engineers inherit a codebase from a phase where velocity was the point. The audit is real engineering work, and the failure mode is treating it as a cleanup pass that can be absorbed into the first sprint. It has to be scoped and scheduled like any other phase or the whole model quietly collapses back into shipping the prototype.
A method whose first two phases are funded deliverables has to be sold as exactly that, and the instinct sitting across the table is to treat the prototype as the finish line and call the engagement done. Rigor is a harder sell than speed, and it gets harder still when a competitor is quoting the prototype alone and calling it a product. The honest version of this cost admits that the method can be entirely right and still lose the bid, because the client is not always buying the thing that will still be running in three years. Holding the line means walking away from engagements priced against the wrong artifact rather than rewriting the method to fit the artifact someone else is willing to sell.
And there is the same cost I paid the first time. Codifying a process means somebody’s judgment wins, and engineers who disagree are now arguing with a document instead of with a colleague. Adoption still works better dictated from the top than discovered by each team on its own, and each team still tries to put its own spin on it first.
Why the cycles got longer
The overhaul used to arrive on a predictable schedule, two or three years in, when the assumptions the original architecture had been built on turned out to be wrong. They were not wrong because anyone was careless. They were wrong because they were made in a phase where nothing existed to test them against, and by the time the product could contradict them it was expensive to listen.
Moving the first running artifact to the front of the engagement moves that contradiction to where it is still cheap. What survives into the engineering phase is a set of assumptions a real user has already argued with. If that holds, the overhaul stops arriving on a fixed schedule and becomes optional, with a product running for years on incremental releases instead of waiting for a rewrite it can no longer avoid. That is the prediction the method makes.
What I would need to prove it
Elapsed time from the first conversation to a prototype the client has actually used is one measure. The change in scope between demo sign-off and the first production release is closer to a direct test, because it is the clearest read on whether the assumptions carried forward were better than the ones the old process carried forward. Measured token spend on the demo against measured spend on the final build is the multiplier the whole cost-control argument depends on, and it either holds across engagements or it does not. The length of a product cycle under this method, set against the two or three years the old overhaul interval ran, is the slowest measure to arrive and the one that would settle the argument outright. Those are the numbers the method should be held to, not a claim that it has already been proven.
The transferable claim does not depend on which model is current: the phase that is cheap to be wrong in is the one worth spending on, and a process should be priced against the phase it governs rather than applied evenly across all of them.