AI coding agents can now write a working pull request in minutes. That sounds like the whole problem solved. It is not.
When code is cheap to produce, the constraint moves. The question is no longer "can we write this?" It becomes "can we trust what was written enough to ship it?" If every AI-generated change still needs a human to read it line by line, you have not removed the bottleneck. You have moved it onto your most expensive people and added a queue.
So the goal was never to produce more pull requests. The goal was to produce trustworthy, shipped software — and to make trust something the system earns by construction, not something a reviewer grants by reading every line.
Our software development lifecycle is built around a simple idea: if you want to trust AI-written code, you have to engineer the process around it, not bolt the AI onto a process designed for humans.
Why bespoke
The obvious move is to pick an off-the-shelf agent framework and run with it. We evaluated several, ran gap analyses against what we actually needed, and weighed the trade-offs.
We chose to build our own. Not because the frameworks are bad, but because the value is in the process itself, and that process needs to be ours to shape. A generic orchestration layer gives you concurrency and dashboards. It does not give you the specific, hard-won fixes for the specific ways AI gets your codebase wrong.
What we built instead is a harness: a deterministic layer that wraps the AI and enforces how it works. Branching, committing, running the full test suite, kicking off review — the harness makes these things happen the same way every time, rather than hoping the model remembers. It is deliberately a vehicle for continuous improvement. When we discover a new failure mode, we encode the fix in the harness, and every future task inherits it.
We also kept the design model-agnostic. Model pricing and capability shift constantly, and the ability to swap or mix models — even to run different models against the same task — is worth more than a tidy single-vendor setup.
The lifecycle
Work flows through a small number of stages. Each one has a clear owner, human or AI, and a clear definition of done.
- Issue. A human raises a problem or an objective. This is where direction comes from.
- Discussion. AI and human refine the issue together — clarifying the problem, exploring solutions, and writing acceptance criteria. Large issues break down into smaller ones, recursively.
- Build. AI agents implement against the acceptance criteria, inside the harness, running tests as they go.
- Adversarial review. Independent AI reviewers try to find what is wrong — completeness, quality, security — before anything reaches a human.
- Human gate. A person makes the final judgement, working from a plain-English summary rather than the raw diff.
- Learn. What we discovered during the issue feeds back into the policies and context that govern the next one.
The rest of this piece walks through the parts that make this more than a flowchart.
Discussion first
Most of the leverage is at the front. Traditional sprint planning becomes an AI-assisted discussion: an issue is decomposed into a problem statement, candidate solutions, and a decision about whether it is ready to build or needs to break down further.
This replaces the all-or-nothing sprint with continuous, recursive refinement. A tiny fix gets minimal discussion. A complex feature gets decomposed into sub-issues — by AI suggestion, with a human able to override scope. The output of the discussion phase is not a vague ticket. It is a structured brief precise enough to act as a technical specification.
Acceptance criteria as a contract
The single most important artefact in the whole system is the acceptance criteria. They are the contract that defines "done" — and crucially, they let the AI judge its own work deterministically instead of guessing when to stop.
This is where vague work goes to die. Loose or incomplete criteria produce long, wandering build loops and force manual review back into the process. Precise criteria do the opposite: they let the build and review loops terminate cleanly. Over time we have pushed criteria to cover not just functional behaviour but performance and usability, so regressions get caught by the contract rather than by a person noticing later.
End-to-end tests that simulate real user interactions give those criteria teeth. They turn "it should work" into a deterministic check the harness can run on every change.
The harness
Left to its own devices, an AI session forgets to commit, runs tests only on the files it touched, and tangles itself up the moment two pieces of work overlap. The harness exists to make those failure modes structurally impossible.
It isolates each task in its own working tree, forces a commit before any task can be marked complete, and routes every change through a single test entry point so the full regression suite runs — not just the tests near the change. It manages branching and merge handling as a normal part of multi-stream development rather than a thing a human has to hold in their head.
The payoff is cognitive: the developer stops tracking which branch is in which state and what still needs committing, and spends that attention on the problem instead. The harness carries the bookkeeping; the human carries the judgement.
Adversarial review
The instinct is to ask the AI that wrote the code whether the code is good. That does not work. A single session grades its own homework generously.
So review is done by independent, fresh sessions with no stake in the work. Asked cold whether a change meets its acceptance criteria and whether it is secure and correct, an independent reviewer reports gaps far more honestly than the author. We run these as adversarial loops — multiple reviewers probing for completeness, quality, and security — and as scope grows we add specialised reviewers, including dedicated security passes.
Because we are model-agnostic, we can run different models as reviewers and exploit their different blind spots. A weakness one model glosses over, another tends to flag. The result is a review process that catches more than any single model, single session, or single tired human would.
Human judgement, not human typing
Humans stay firmly in the loop — but at the right altitude. People set objectives, prioritise, curate context, and make the final call. What they stop doing is reading every line of generated code.
Instead, the independent reviewers produce a high-level summary in plain English: what changed, which architectural trade-offs were made, where the risks are. The human reviews the reasoning and the decisions, not the syntax. That keeps people oriented around the architecture of the system even as the line-by-line authorship shifts to AI.
This is a real shift, and we are honest about its tension. Lean too hard on the AI too early and you lose your grip on how the system behaves. So the human gate is heavy at first and gets lighter only as the policies and harness earn that trust. The direction is clear — less manual review over time — but it is earned, not assumed.
When something does go wrong, we resist fixing the code directly. The more durable fix is to repair the instruction, the policy, or the context that let the AI get it wrong — so the whole system improves, not just one pull request.
Policy as code
The behaviour of the system lives in version-controlled documents, not in people's heads. Coding standards, testing approach, branching strategy, architectural guidance, security priorities — all written down, all reviewed through pull requests like any other code.
We separate two kinds of knowledge. Policies are cross-project and portable — how we test, how we branch, what good looks like. Context is project-specific — the business domain and the technical decisions behind a particular system. The AI reaches for the right slice on demand through progressive disclosure and search, rather than being force-fed everything.
We are deliberate about curation. Carefully maintained context beats a firehose of raw transcripts and stale wikis; noisy or contradictory inputs make AI decisions worse, not better. Onboarding a new project means bringing these policies in, running a gap analysis against what the repo already does, and reconciling the two — increasingly automated so each new project starts from the same standard.
Compounding gains
The reason this is worth the effort is that the improvements compound.
After an issue closes, the AI proposes pull requests that update the policies and context with what was learned. A human curates those changes. The next issue runs against a slightly better system. Most of our engineering effort goes here — into the harness and the policies — rather than into one-off fixes, because an improvement to the harness pays off on every future task.
The benefits we are after, in order of how much they matter:
- Trust by construction. Changes arrive already tested and independently reviewed, so a human can approve on judgement rather than line-reading.
- Throughput with reliability. More gets shipped, without trading away the confidence that it works.
- Higher-altitude work. Developers spend their time on architecture and acceptance criteria, not on branch bookkeeping and boilerplate.
- A system that improves itself. Every issue leaves the harness and the policies a little better than it found them.
- Quality as a discipline. Because AI compounds on whatever it is given, strict standards from day one keep technical debt from snowballing.
Production bugs are the one deliberate exception. They skip the discussion phase and jump straight to the build-and-review path, because speed matters more than ceremony when something is broken in front of a customer.
How we put it together
None of this arrived fully formed. It came out of a run of working sessions — design workshops to define the first version, then a standing weekly review where we walked through what was breaking and what to encode next.
The shape of it: one engineer led the core lifecycle design, others brought a holistic view of discovery and framing, multi-mode workflow ideas, and multi-model review techniques, while the commercial side kept pressure on velocity, cost, and client impact so the process stayed grounded in delivery rather than becoming an end in itself.
We made the build-versus-buy call early, stood up a shared repository for the policies and the harness, and piloted on real client work rather than a toy project — small, low-risk tasks first, to build confidence before widening scope. Each week surfaced new edge cases; each edge case became either a policy update or a harness improvement. The lifecycle you have just read about is the accumulation of those rounds.
Where it goes
The destination is a lifecycle where humans set direction and exercise judgement, and the system handles the mechanical distance between an agreed problem and shipped, verified software.
We are not all the way there, and we are clear-eyed that getting there is earned in small increments — each one paid for by a process that gets a little more trustworthy every week. But the direction is set, and the trajectory matters more than the current position.
The lesson, if there is one to take away: the hard part of AI software development is not the writing. It is building the process, the contracts, and the review that let you trust what was written. That is the work.