For years we ran on triage.
One customer needed it to launch, another had waited three weeks on a fix, a third had paid for ten things that didn’t work. We took the loudest first.
That system fit the constraint we had. We build software for food and beverage plants, and they wanted more than we could make, so we optimized for shipping: sprints, estimates, standups, and reviews that caught mistakes before they cost a week.
Then delivery stopped being the scarce thing.
Over a few months the monorepo became a harness, a layer of context and skills and conventions and commands that an agent reads before it touches anything. Where a machine can check done, nobody sits inside the loop. A person writes the contract at one end and reads the result at the other. It covered the work we expected it to cover, and then the work we’d assumed would stay manual: migrations, service internals, frontend features, the hard parts of the product. All of it shipped, and it stayed shipped.
Building that harness was the strangest project we’d run. Nothing told us it was working. No test says the agent is good enough at frontend now, so every few weeks we read a stack of output, decided whether we’d gained anything, changed the context, and ran it again. It took months. We couldn’t tell you which round mattered, and we had no name for that kind of work at the time.
We beat a problem we’d fought for two years, and it didn’t feel like winning. We still felt stuck.
Our constraint had moved from throughput to judgment, and every practice we own was built for the old one. The clearest break runs along the line between work with a knowable done and work where done keeps moving. We’d been running both through the same process the whole time, and it only ever fit one of them.
The constraint moved
Agentic engineering didn’t make our engineers better. It made a whole category of work close to free.
A ticket that used to consume a person’s week comes back in an afternoon with nobody watching it, and the tooling around the harness keeps widening that gap. Ticket throughput no longer holds our risk.
Judgment went scarce instead, in two forms: knowing what’s worth building, and being able to tell whether what came back is any good.
Neither speeds up with more agents. Reviewing a design still costs an hour of somebody’s whole attention, and deciding whether a workflow change survives contact with a plant floor still needs someone who has stood on one.
The cost structure inverted too. Building the wrong thing used to cost a quarter, which made it rare enough that people weighed it. Now it costs a week. You can do it fifty times a year, stay busy, ship all of it, and arrive nowhere.
A backlog says nothing about direction
A backlog looks like a roadmap. It’s ordered, it’s dated, and it holds everything we intend to build, so people read it as a statement of direction.
The items come from escalations, sales promises, bugs, and requests, and every one of them defends itself on its own terms. Nobody picks the direction. It falls out of the addition. Grind that list long enough and you ship a product that answers every request and stands for nothing.
Nobody asked what we’re trying to become. That question lives a layer up from the queue, and we never built a place for it.
An answer looks like a small number of bets sitting above the queue. Three or four, written as theses rather than features, each one specific enough to be wrong. Not “improve the manufacturing experience,” but something you can hold against a quarter of shipped work and lose.
The backlog survives all of this. It just stops being the top-level object. A roadmap item either argues for itself against a bet or gets called what it is, which is keeping the lights on, and we need both kinds. The cost comes from confusing them.
Bets have to be killable. A thesis nobody will abandon after two quarters of evidence amounts to a slogan, and the value of the whole exercise is being able to say we got that one wrong, with the shipped work to prove it. Then the argument moves up a level, which is where an argument is worth having.
flowchart TB
subgraph s2["A thesis decides"]
direction TB
T["Bet: we win by owning X"] --> Q2["Work that advances the bet"]
Q2 --> P2["A product with<br/>a point of view"]
L["Keep the lights on"] -.-> P2
end
classDef hi fill:none,stroke:#8b5cf6,stroke-width:1.5px
class T,P2 hi
subgraph s1["Requests decide"]
direction TB
A1["Escalation"] --> Q1["Backlog"]
A2["Sales commitment"] --> Q1
A3["Bug"] --> Q1
A4["Feature request"] --> Q1
Q1 --> P1["Whatever the product<br/>ended up being"]
end
I’m not certain that’s the right mechanism. The problem underneath it I’m sure about. Shipping the next item on the list looks exactly like shipping something that moves the product toward a goal: same velocity, same burndown, same demo. The difference surfaces a year later, in whether the product landed somewhere on purpose.
Shaping tells you how to build something well. It doesn’t tell you why this and not the fifty other things, and that question belongs to everybody now.
Two kinds of work
We reviewed this year’s project history to find what pushes a project off track.
Estimate size didn’t predict it. Team didn’t. Neither did anything we’d normally call complexity. One thing did, and it was whether the project had a knowable done.
Deterministic work has one. Data mapping, exports, a screen, an integration against a written spec. You write down done before you start and hand that definition to a machine, as unit tests, integration tests, end-to-end runs, or agents that poke the product and report back.
A machine does the verifying, which is why this whole category got cheap when writing code got cheap.
It also closes the loop without us. A machine that can judge the work can keep trying until it lands. You write the criteria, hand them over, and read what comes back, and nobody stands in the middle. Deterministic work makes a handoff.
Convergence work doesn’t. Consider the onboarding a new plant walks through before anyone on our side picks up a phone, the thresholds that decide which alerts reach a supervisor at two in the morning, a price, or a forecast. Done sits at a threshold on a number, and no threshold holds up in advance. Ninety-two percent might make a product. It might mean nothing. The way to find out is to show it to someone who knows how the number gets used and let them decide. You walk toward a target you keep redrawing as you walk. No test settles that, and no agent settles it either, not because the models fall short but because the thing doing the optimizing can’t judge when to stop.
| Deterministic | Convergence | |
|---|---|---|
| What done means | A check that passes | A threshold on a number |
| Who decides | The criteria | A person, against the business |
| Who does it | An agent, end to end | A person, with agents running turns |
| Verification | Mechanical, and cheap now | Judgment, and still costly |
| Shape | A line | A loop |
| Failure | A slipped date | Never stopping |
flowchart LR
subgraph c["Convergence"]
direction LR
F["Floor"] --> T["Try"]
T --> M["Measure"]
M --> J{"Good<br/>enough?"}
J -->|"No"| T
J -->|"Yes, or budget spent"| X["Decide, then stop"]
end
subgraph d["Deterministic"]
direction LR
S["Scope"] --> B["Build"] --> V["Checks pass"] --> DN["Done"]
end
classDef hi fill:none,stroke:#8b5cf6,stroke-width:1.5px
class DN,X hi
You can see it in our own history. Convergence projects grow V2s: a project closes, and a new epic appears carrying work the first one promised. That isn’t sloppiness. We cut a shippable line through unfinished work, call it V1, get it to customers, and carry on under a new number.
Drawing the line is the right instinct, and recording everything behind it as complete is where we go wrong. V1 ran round one of a loop we never planned as a loop.
Build the floor first
One project this year taught us more than the rest together. It spent months building on ground that wouldn’t hold, and not one of those runs told us anything.
- The fields the model trained on sat empty, and nothing filled them.
- A stretch of history lacked the identifier that attributes it.
- The eval returned a confident number from a run that measured nothing.
- Two sources disagreed, so the instrument moved between runs.
- No naive baseline existed, so no result could beat doing the obvious thing.
None of that is a people problem. It comes from starting the convergence work before finishing the deterministic work underneath it, and teams do that because the convergence part is the interesting part.
Build the deterministic floor before you spend a week converging on top of it. Not early. First.
The floor is three things: clean data, an eval you trust that scores a result the same way twice and tells you when it got worse, and a naive baseline, the dumbest thing that could work, so you beat it or lose to it on day one.
flowchart BT
subgraph floor["The floor, all of it deterministic"]
direction BT
D["Clean, populated data"] --> E["An eval you trust"]
E --> B["A naive baseline to beat"]
end
B --> T["Tuning"]
T --> R["A result you can believe"]
classDef hi fill:none,stroke:#8b5cf6,stroke-width:1.5px
class R hi
Without the floor you don’t converge. You wander. Every round takes a step, nothing scores the step, and the next one starts as blind as the last. Gradient descent with no gradient. Run it long enough and you get motion, a burn rate, and a report at the end that means nothing.
That trade holds if tokens come free and the quarter never closes. Tokens come close to free. Quarters close on the day they always did, and the attention we spend reading those runs stays the dearest thing we own. A floor costs a week. Skipping it costs the months that follow and takes the evidence with it, because a project without a floor can’t even tell you it failed.
Nobody skips it on purpose. It goes missing because it looks like setup, plumbing before the real work. It carries no demo and no headline, and the project plan calls it week zero. Then a quarter later the numbers come out clean and worthless, and every hour spent on top of that missing week goes in the bin.
Look at what the floor is made of, though: clean data, a working harness, a stub. All of it knows its own done, and a machine can check every piece. Every convergence project has a deterministic project hiding inside it, and that hidden project decides whether the visible one means anything.
What a floor unlocks
Building the floor pays for itself twice. Once because it makes the results worth believing, and again because it lets us point agent loops at convergence work.
Convergence runs as a loop: try, measure, choose what to try next. The trying used to cost the money, so a person sat inside every turn and the loop ran at the speed of that person’s week. The trying comes close to free now, so the turns can run unattended.
The round becomes the unit. A turn makes one attempt against the metric. A round gathers turns and ends in a decision. Agents own turns. People own rounds. That line holds, because a round boundary asks the one question the optimizer cannot answer: does this number serve the business well enough.
Three shapes of this work for us today.
Research loops. An agent runs an experiment, reads the result, forms the next hypothesis, and carries on without waiting for anyone. Hand it an eval and the set of knobs on our alerting rules. It replays six months of plant events, counts how many alerts each configuration would have put on a supervisor’s phone and how many of those turned out to matter, drops the settings that earn nothing, and moves to the next combination. You get a ranked table with the log of every run behind it. A week of somebody’s mornings becomes an afternoon.
Self-improving prompts. The loop rewrites its own brief each round, so round ten starts clearer than round one. Take a prompt that maps a supplier’s spreadsheet onto our schema. The first version mangles the ambiguous columns, so the loop reads its own failures, writes rules to catch them, and runs again. What comes out sits in the repo carrying what twenty runs taught it, and the next integration starts there instead of from a blank file and somebody’s memory.
Completion conditions. Write down what finished means and let the loop run until it gets there. Both tenants five points above baseline, or twenty variations spent, whichever comes first, then write up what you found. That maps onto convergence work without any translation. A completion condition states the stop we agreed at kickoff in a form a machine can act on. Writing one forces the clarity we needed anyway, because nobody writes a stop condition and stays vague about good.
Two limits, and both weigh more than the upside.
A loop amplifies its eval. Point one at a harness that reports confident numbers from empty runs, and it optimizes against noise faster than any person could, then hands you a clean report. Speed cuts both ways here. On a good floor the loop buys a week of iteration in a day. On a bad one it buys a week of being wrong in a day, and the report reads the same either way. The floor decides whether the loop produces anything at all.
The second limit cuts deeper. A loop climbs the hill it stands on. It finds the top of the approach you handed it, faster than a team would, and it never tells you the hill sits in the wrong place, or that the last four points of accuracy stopped mattering to the customer.
Agents run the turns. We choose the hill, and we call the stop.
Most features hold both
Sorting work into two kinds makes it sound like a feature arrives as one or the other. Very few do. A convergent core comes wrapped in ordinary work: the data that feeds it, the screen that shows it, the record of what it decided, the job that runs it at three in the morning.
Take a suggested reorder quantity. The suggestion converges. Pulling the inputs, storing the result, putting the number on the screen the buyer opens each morning, letting them change it, recording the change, all of that knows its done and always did.
The mistake is to size and sequence the whole thing as one unit, with one epic and one estimate and one release. Nothing ships until the number gets good, and the number never gets good, because nobody outside the room says what good means. Four months later a deadline carves out a V1, and a V2 carries the rest.
Convergence hell is a decomposition failure, not a discipline problem and not a modelling problem.
Find the seam. A line runs through the feature with the convergent part on one side and everything else on the other. Draw it, and make it a contract: a function signature, an interface, a service boundary. Give it a shape that survives whatever stands behind it.
Then the sequence writes itself. Week one ships the envelope with the naive baseline behind the seam, whether that’s last quarter’s average or the supplier’s minimum order or whatever dumb thing works. You had to build that baseline anyway, since it makes the third piece of the floor. It goes to a customer now instead of into a benchmark table.
flowchart LR
IN["Inputs and pipeline"] --> S{{"The seam:<br/>one contract"}}
S --> UI["Surface, override,<br/>record of what changed"]
V1["V1 naive baseline"] -.-> S
V2["Round 2 model"] -.-> S
V3["Round 3 model"] -.-> S
classDef hi fill:none,stroke:#8b5cf6,stroke-width:1.5px
class S,V1 hi
The envelope has to survive a weak core, and that’s a design constraint like any other. Call the output a suggestion rather than an answer, let people override it, and record what they overrode and by how much. If the screen can’t ship with something mediocre behind it, fix that in week one while it costs little.
Now two clocks run instead of one. The feature finishes when it meets its contract: shipped, checks green, ticket closed and staying closed. The core keeps running rounds against the metric on its own budget, and each version lands behind a seam that carries traffic. Nobody reopens the feature to improve the model.
The seam cuts more than code. Outside it, work makes a handoff, with criteria going in and software coming out and nobody standing over it. Inside it, somebody stays. The seam tells you what the estimate never did, which is how many hours of your team’s attention this feature demands. The number comes back smaller than anyone guessed, and it sits in one place.
Look at what the shipped baseline bought. No threshold holds up in advance, and no planning meeting settles it, but a live baseline does. If buyers take the suggestion four times in five, the number works and round two turns optional. If they override everything, you learn that in week two instead of month five, with the failing cases in hand.
One case breaks this. Where a wrong answer can’t be undone, where money moves or a compliance record gets written or something reaches a customer’s customer, the envelope can’t absorb a bad core and shipping the baseline ships a defect. Send the same slice inside first. Same seam. Same override. Same record. Our own people at the other end. The slice stays the unit of delivery, and the baseline stands as a real implementation of it.
Write the whole feature out as tickets and the order settles itself. Take the suggested reorder quantity again, in the form somebody would actually file it.
- Consumption history and on-hand stock, pulled into one table.
- The supplier lead times that half the items lack.
- An eval that scores a suggestion against what the buyer ordered.
- One contract: item and site in, quantity and reason out.
- Last quarter’s average, behind the contract.
- A panel on the purchasing screen.
- An override, with a field for why.
- A record of every suggestion and every change.
- The job that runs it before the buyers arrive.
- A model that beats the average.
Ten requirements. One of them converges.
The old instinct draws a dependency graph and walks it. That graph misleads us now, because it ranks the work by what the code needs, and writing code comes close to free.
Order by decisions instead.
Three items block everyone: the data, the eval, and the contract. Nobody measures anything before the first two land, and nobody builds against a shape that doesn’t exist. Those three make the critical path, and the other seven block nobody.
After the floor, the work splits into two lanes.
One lane runs wide. Hand the panel, the override, the record, the job, and the backfill each to an agent with its criteria, and start them together. They don’t queue behind each other, and none of them queues behind the model. Six people would have run them in some order across six weeks, and the work never needed an order.
One lane runs single file: a round against the eval, then a call, then another round. Each round reads the result of the last one, and the same person makes every call, so the lane can’t widen. Judgment doesn’t fan out. Hand somebody two convergent requirements at once and they’ll run them in series anyway, slower, with less attention on each.
Agents fill that lane too. They run the turns inside every round, dozens of them, while nobody watches, and what they can’t run sits between the rounds. The narrow lane holds no less machine work than the wide one. It holds a person at each boundary, and the boundaries set its pace.
Serialize judgment. Parallelize everything else. The critical path runs through the calls and through nothing else.
The wide lane has a ceiling, and headcount stopped setting it. Every agent that finishes hands back something a person has to read, so fan out twenty and the queue moves from the keyboard to the reviewer. Width belongs to whatever one person can judge in a day. We can measure that, and we seldom do.
Order the narrow lane by what could kill the feature. A round boundary pays only while stopping stays cheap, and stopping gets dear once the surface, the record, and the job all exist. Ask the question that could end the project in round one, before the wide lane has spent much.
Week one lands the floor, the contract, the panel, and last quarter’s average, and the buyers see a number. The wide lane finishes a few days behind it. What remains runs single file, one round at a time, behind a seam that carries traffic. Nine requirements finish and stay finished. One keeps working, and it blocks nothing.
Long does not mean fuzzy
One integration has run seven months. At a glance it fits the pattern.
It doesn’t fit at all. The scope held from day one. What grew were the distributed-systems edges: status reversals arriving out of order, charges and discounts that have to survive a round trip through a partner’s system, load spikes most teams never meet.
A framework applied without care does more harm than no framework, and a long timeline proves nothing about a fuzzy target. Sometimes the map lied about the terrain.
A loop would have helped there, just not the convergence kind. That project spent its money finding edge cases, and finding things is a search problem. Point an agent at the partner spec, have it write hostile payloads, replay them through the integration, and report what breaks, then let it run while you work on something else. Done stays knowable and the check stays mechanical, so the loop enumerates instead of converging. That work belongs in week one.
What the ceremony managed
Look at what the old lifecycle moved around.
Estimates forecast a queue. Grooming fed the queue. Sprints cut it into batches a fixed team could carry. Standups caught the handoffs, because people drop things. Team shaping decided how much queue each group could hold. Scope, spec, build, deliver, and a ritual at every seam between them.
Every one of those answers the same question: how do we wring the most out of a scarce, serial, human ability to write code. We no longer have that scarcity, so the ceremony now measures the one thing we hold in surplus.
An estimate costs more than the ticket it estimates. Grooming feeds a queue nobody stands in. A standup reports on work that ran overnight while the team slept. A sprint boundary batches capacity that stopped arriving in fixed amounts. Team shaping spreads a shortage we don’t have.
None of that argues for no process. It argues that our process solves a solved problem, and the one we need doesn’t exist yet. The new one runs thinner and weighs more: three or four bets, a classification per requirement, a seam, a round budget with a stop condition, and a plan somebody read before the week of work existed. Five decisions in place of forty meetings, and each decision costs more than the meeting it replaced.
The ceremony also did work nobody wrote in the charter. It put people in a room, showed them the same board, and gave the week a shape. Take it out and the hole stays open, and whoever takes it out owns filling it.
At the companies furthest along, most of this has gone. The rest will follow, and not because someone wins the argument. A team that spends Tuesday grooming a backlog competes with a team that spends Tuesday deciding what to build. One of them ships a product with a point of view. The other ships the list.
What changes
Naming the two kinds is the easy part. The change sits in how we plan, staff, review, and decide we are finished.
Two kinds of work, two contracts
Everything moves through one shape now: scope, size, build, review, close. That shape tells the truth about deterministic work and lies about the other kind.
Deterministic work keeps it and grows stronger. Write the criteria first, encode them as checks, and hand the whole thing over. Two human questions survive, one at each end. Does this deserve building, and did we get what we asked for. When code and tests both come cheap, the risk moves out of execution and into whether the thing belonged on the list at all.
Convergence work needs its own contract: a floor before the first week of tuning, a metric everyone accepts, a budget counted in rounds rather than weeks, and a stop condition written down before anyone loves the outcome, so that the target lands or the rounds run out, whichever comes first. It also needs a named owner for the rounds, because agent-assisted doesn’t mean unowned. A loop with nobody at its boundaries just spends money.
Rounds get planned
If we expect a project to need three rounds before it earns its place, we say three rounds at kickoff, and we say what each one buys.
Round one buys the floor and the baseline. At the end we can measure, we know what doing nothing clever looks like, and if the seam allows it, the slice already serves customers. Round two makes the first real attempt and answers one question: did we improve enough to pay for a third. Round three buys whatever it takes to put the thing in front of a customer without an apology attached.
flowchart TB
R1["Round 1<br/>floor and baseline"] --> D1{"Decide"}
D1 -->|"Continue"| R2["Round 2<br/>first real attempt"]
D1 -->|"Stop"| E1["Nothing shipped,<br/>and we know why"]
R2 --> D2{"Decide"}
D2 -->|"Continue"| R3["Round 3<br/>good enough to show"]
D2 -->|"Ship what we have"| E2["V1 out, loop closed"]
R3 --> E3["Ship, or spend<br/>another budget"]
classDef hi fill:none,stroke:#8b5cf6,stroke-width:1.5px
class E1,E2,E3 hi
Each boundary holds a decision rather than a milestone: continue, ship what we have and stop, or stop with nothing. All three deserve respect, and agreeing on that at kickoff is what makes the third one possible.
Loops make rounds cheap without making them optional. A round that took three weeks takes three days, so more rounds fit the same budget, which means more decision points rather than fewer. Agents run the turns, and somebody stands at every boundary and makes the call.
Planned this way, a V2 is the loop working. Discovered after the fact, a V2 is evidence we told ourselves a story about being finished.
Classification opens a conversation
At the start of a project, someone asks whether we can write down what done means in a form a machine can check.
If we can, the project is deterministic, and it should feel fast and dull. If done is a number somebody has to judge against the business, it needs a floor and a round budget before anyone starts tuning.
The answer also decides where our people go, which is the part that costs something. One answer hands the work away; the other commits somebody’s attention on purpose, at planned intervals, for a fixed number of rounds.
flowchart TD
A["A project starts"] --> B{"Can done be written<br/>as a machine check?"}
B -->|"Yes"| C["Deterministic<br/>criteria, checks, a date we defend"]
B -->|"No, someone has to judge it"| D["Convergence<br/>floor, metric, round budget, stop condition"]
classDef hi fill:none,stroke:#8b5cf6,stroke-width:1.5px
class C,D hi
Most of the time the honest answer is which parts, not which kind, and that’s the more useful question anyway, because answering it locates the seam and the seam lets the deterministic part ship on its own clock.
The answer isn’t always obvious, and a project sometimes turns out to be one wearing the costume of the other. The value sits in asking early and out loud, rather than working it out eight months in, from the wreckage.
Judgment gets the calendar
If judgment holds the limit, a calendar full of mechanical work means we still staff the old constraint. An hour spent inside deterministic work goes to the one thing that no longer needs us.
The time goes instead to choosing what to build and to reading what came back, and the people carrying the most context spend it on the questions agents can’t answer.
The same shift applies to review. Ours was built to catch mistakes in code. Most of what hurts us now starts as a mistake in intent, and a plan holds those cheap. Nobody rejects a merge request over “this assumes every lot has one supplier.” They say it against a plan, in one sentence, before the week of code exists. When a week buys what a quarter used to buy, the leverage moved to the plan.
Hiring points elsewhere as well. We don’t lack delivery speed. We lack people who can look at a workflow, a threshold, or a plan and say with authority whether it holds up.
Done stops meaning closed
Deterministic work finishes when the checks pass. Convergence work ends when the metric clears the bar we agreed, or when the rounds run out and somebody makes the call.
Tickets closed stops being a measure of anything. It always stood in for delivery capacity, and delivery capacity stopped being scarce.
We spent years on a throughput problem and we beat it, and a judgment problem was waiting behind it. One kind of work we can hand away now. The other stays ours, and no better model takes it off our hands. It needs a different muscle and a different operating system, and I’d rather build that on purpose than find it one V2 at a time.