Meeting in the Middle

When I was a child my mother took me to St. Louis, Missouri so that I could see the famous St. Louis Arch, Gateway to the West. Riding up to the observation room at the peak of the Arch was a thrilling experience, as was looking down through the windows into the open space below. But the most remarkable part was not the frightening heights or the ratcheting barrel-like elevators that rotated as they carried visitors up the narrow, curving shafts to the observation room. It was the illustrations in the underground archive beneath the Arch's foundations, showing how the whole thing was made.

They did not build the Gateway Arch the way you build almost anything else... because of the shape, they couldn't just start on one end and work their way to the other, nor was building it lying down and simply standing it up an option. Instead, they started at both feet at the same time and built toward the middle: two legs welded upward from opposite foundations, each a free-standing cantilever leaning further out over the open space with every section, on the premise that when the legs finally reached each other, 630 feet up, the final segment would drop into a gap engineered to a tolerance of one sixty-fourth of an inch.

The two crews did not coordinate their welding per-se as they went up piece by piece... what made it work was that they agreed, in advance and to the sixty-fourth of an inch, on exactly where the legs would meet in the open space above them. Everything else was independent and, to some degree, uncertain. The meeting point and the agreements that defined it, however, were sacred.

I recently ran a software build the same way; this is the story of what happened.

Adversarial Agentic Coding

Every methodology book says the same thing: get the requirements right first, write them down, make them testable, freeze the contract before you build. In twenty years of shipping software I have watched approximately everyone, myself included, nod at that and then not do it. Not because it wasn't possible, and not even because it was time consuming or expensive... but largely because people rarely know what they want before they start building and, even worse, because nothing ever really forced them to be explicit about what their software must (and must not) do up front. The spec, the code, and the tests came from the same head or heads, loosly documented to make room for the inevitable change of direction and expansion of scope creep... and free to quietly reconcile any gap after the fact. When the test failed, it was easy to just tweak the test to match the code or, worse, adjust the code to pass the test and get the deployment without really understanding what it is the tests were actually trying to test. All too often, it seemsed, requirements were a formality you back-filled to match what you built.

But I felt I could (and should) do better... so this week I removed the ability to cheat. The experiment was adversarial coding: two AI teams in two separate seats, with the agreed-upon requirements and myself, posing questions and orchestrating turns between build and test, as the only channels between them. Blue team was Claude Code, positive, eager, a genuinely good creative build partner: it wrote the specification and the implementation. Red team was Codex, serious and strict, particularly when asked to be: it read the frozen requirements, tried to break them on paper, and wrote the tests that would hold the build to account. Red's working rule was written on every one of its cards: tests derive from the agreed requirements, not from the blue-team implementation. The two worked on separate branches. Blue never saw Red's tests; Red never saw Blue's code. Neither side could bend toward the other in private.

That is the whole trick: visibility in the contract, opacity in the build. Because the implementation is hidden from the tests and the tests are hidden from the implementation, there is no way to back-fill agreement later. All the coordination pressure concentrates on the one surface both teams share, the written requirements, which are suddenly load-bearing because they are the only place the two halves are allowed to touch. If the contract is vague, the legs do not meet, and there is no quiet weld at 3 a.m. to fix it.

The tension in this arrangement is not competitive. There is no apex to win alone; one leg of an arch that races to the top only to arrive at the wrong location in space does not win, it fails, and takes the other leg with it. The blindness was never secrecy for advantage... it existed to keep both sides honest: no bending a test to bless the code, no tuning code to flatter a test. And I was neither blue nor red. I set the scope, owned the tolerance, and carried verdicts across the seam; the human is the one who fits the keystone, because a keystone set by one of the legs is just that leg deciding it was right all along.

The feature we built I named Tōmi (遠見 in Japanese, meaning "far-seeing"): a remote window into Tanzaku, our internal project tracker, which lives loopback-only on a dev server (because localhost-only is its security model). The design: the public-facing Auth/Technic site becomes an authenticated reverse proxy serving the real board over a private link to the dev box, injecting credentials server-side, of course, so the browser never holds a key. This would enable me to see and operate my kanban board on my dev hardware from any location, removing a remote-work bottleneck on the project management side similar to the one Claude remote-control had done for the coding side.

The Contract and the Code

Blue crafted the scope of work and proposed the agreement... while red's first go/no-go audits came back blunt: NO-GO pending three contract corrections. The best catch is worth telling in full (and here we get into the weeds just a bit, bear with me).

Tanzaku stamps every change with an actor, claude or alex, in an append-only audit trail. Remote changes needed an additional actor, tomi, so the ledger would honestly record which edits came through the remote window. Blue's first design trusted a header: any request bearing the API key could assert X-Tz-Actor: tomi, on the reasoning that only the proxy holds the key. Red refused it flat: the same key is held by local CLI and MCP tooling, so any local script could stamp tomi and quietly corrupt the audit trail, forever. The signature would have been forgeable the day it shipped, and worthless silently, which is the worst way. Blue's fix made attribution credential-derived: a dedicated Tōmi credential whose authenticated identity mints the actor, with tomi reserved so no ordinary caller can claim it.

The other contract rounds were the same lesson at smaller scale: a tunnel credential specified as "or equivalent" (you cannot write a test against "or equivalent"), an admin-dashboard boundary described as "its assets" when the board is one hashed JavaScript bundle (a boundary you cannot point at is a boundary you cannot test), and a "Tanzaku stays unmodified" promise that the attribution fix had quietly falsified, which forced a new card into existence to hold the accommodation. None of these were exotic bugs. Every one was a vague requirement that a normal build would have reconciled into a shipped defect. The adversarial split did not make the AIs smarter; it made the requirements the only place agreement could happen, so the vagueness had nowhere to hide. This is the key to adversarial coding... the source of truth is not what builds or what tests, but rather the single point where both meet, reached through independent yet coordinated effort. The St. Louis Arch felt like the perfect analogue.

The Fittings

As the two halves met, growing closer to each other with each pass of build and test, each fitting measured something.

Blue's first cut of the proxy against Red's blind suite: 47 of 57 passed, 10 failed, four confirmed contract defects (a framework redirect that pre-empted the auth contract, a header denylist where the contract demanded an allowlist, response headers leaking the private hostname, upstream failures bypassing the frozen unavailable response). In a normal build a failing test is a negotiation between two things the same author wrote. Here, each red test was the contract itself, external to both teams, reporting that a weld missed the survey. Nobody could argue the tolerance. And forty-seven welds landing true on the first blind fitting is the result the sermons promise and never show you.

The attribution core came back from its own blind fitting 14 of 14, and then Red found the more instructive thing: docker-compose.yml never passed the Tōmi key into the container. The logic was perfect and inert, correct in every test, unplugged in the real stack. A passing unit test proves the shape of the logic, not that it is wired in. Then the fix for that missing wire introduced the build's most elegant defect: a Compose default of TOMI_API_KEY:-dev-tomi-key, a committed plaintext credential that would silently activate exactly where the real secret was missing. The forge-proof signature we had spent three rounds earning, made forgeable again by eleven characters of convenience. Red flagged it, Blue made it fail closed, Red wrote a test proving it fails closed. Flag, fix, re-check.

The World Pushes Back

Here is the finding I did not expect. Across the whole build, the adversarial pair was close to flawless at code correctness. And not one of the finish-line blockers was a code bug.

The original transport, a Cloudflare Tunnel, died on a fact no test could reach: Cloudflare Access requires the domain to live on Cloudflare, and our DNS lives at GoDaddy. Migrating a whole domain to light one internal window was out of proportion, so it was out of scope, and the transport pivoted to a Tailscale tailnet. The revealing part is what the pivot cost: almost nothing. The proxy dropped one handshake. The keystone, the credential injection, the reserved actor, the dashboard blocks, was mechanism-agnostic, because the adversarial effort had been spent on the part that was actually load-bearing. The tunnel was never a leg of the arch; it was only ever the tram that carries you up.

Then the sharpest lesson of the series, and it cuts against everything above. While exercising the board I went to save a card on the ordinary local board and every mutation 403'd. A Tōmi frontend change had added credentials: 'include' to a shared API client, which made same-origin API-key requests start carrying cookies, which tripped the CSRF middleware. The backend suite, 774 tests, green. The frontend suite, 285 tests, green. Both blind teams, green. The failure lived in a layer none of those tests occupy: a real browser's cookie behavior meeting real middleware. Two teams testing blind is powerful, but independence is not coverage; when neither side reaches a layer, two teams buy you two green verdicts that are blind in the same place. The only thing that caught it was a person trying to save a card. The operator is not redundant with the suites. The operator covers the one layer they structurally cannot.

Go-live proved it again in miniature: the deploy platform silently replaced the container entrypoint, a retry loop could have wedged the whole site, an error was swallowed on the failure path, and three near-identically named credential scopes in the provider's console all failed with the same opaque 403. Blue's own postmortem said it best: the correctness and security logic was rarely the hard part; the expensive failures clustered in platform-integration assumptions and opaque third-party provisioning. The code was the solved part. The world was the hard part.

Browser testing using development mode and captured logs shared with both teams guided the solutions in those final steps... sharing information which helps both sides do a better job is not a negative. In several cases, in fact, the red team provided critical information derived from testing (this is broken, that does not refresh, the other should not be exposed) which allowed the blue team to fill gaps which may have taken far longer to find otherwise. And at each turn, both sides wrote post-mortems which were used as the source for this document and for future learnings.

The Ride Up

Closure was four checks, run in a live browser against production, evidence captured as a network trace that I drove and Red read: a non-super-admin denied; an enumerated dashboard path returning its 404; a card deleted through the real UI returning 204; and the resulting revision visibly attributed to tomi. That last one is the whole arc closing. The defect Red caught first, on paper, before any code, ended as a human watching the live audit trail record a real remote deletion under the honest name.

Three resilience smoke tests were deferred, and the deferral matters as much as the checks: they were written down as explicit accepted risks, not relabeled as pending tasks. One candidate deferral, an allow-all network ACL, was refused that label entirely, because allow-all is not an untested implementation of a port-scoped requirement; it is a departure from it. Naming it a security deviation instead of a chore made the right move obvious, and it was tightened before closure. The delta between what you specified and what you shipped sorts into three piles: what you fixed, what you are paying down, and what you are choosing to leave open with your eyes fully on it. The third pile is where projects lie to themselves. Refuse the relabeling and the board tells the truth.

The Things We Learned Along the Way

I was exhausted by the end, and I want that on the record. The back-and-forth is tedious, and by the last rounds I felt less like an architect than a kid handed the yellow and red cards and a whistle at a World Cup match: the players were faster and better than me, and all I could do was keep the rules on the field. But keeping the rules on the field turned out to be the entire job. The forged signature, the fail-open default, the CSRF regression, the go-live cluster: none announced themselves in the exciting middle. They surfaced in the polishing passes, the punch lists, the rounds I most wanted to be done with. Discipline is not the part of the work you enjoy. It is the part that catches the thing you would otherwise ship... which would inevitably break... and which could take down the entire structure.

The two tools' temperaments were not incidental, either. The eager helpful builder is exactly the personality that ships the fail-open default and calls it done, because being done is a way of being helpful. The strict inspector is exactly the personality that would never ship at all if you handed it the hammer. The method does not fight these natures; it casts them, generous one generating, severe one judging, pointed at each other across a contract, so that each one's characteristic failure is the other one's job to catch. On the same team they would just argue. Across a surveyed seam, that exact difference is what makes the joint true. Most of directing is casting.

And the definition of done is what we were all working toward... and that definition is what the Arch supplied. From a distance, squinting, two joined legs look like an arch... but they aren't. The arch, just like the St. Louis Arch, is not complete until people can ride the elevators up inside it and look out the windows. The code went green long before the project was done; green was the legs touching. Everything after, the operator passes, the live trace, the honest deferrals, was the difference between a shape that looks like an arch and a thing a person can use. That difference is the whole product.

Tōmi shipped. The board opens from outside now, over a private mesh, writes honestly attributed, admin surfaces dark. Red's closing line, from the postmortem it wrote without consulting anyone: "the practice was rigorous, fair to exploratory implementation, and worth repeating". The two legs are joined, the elevators run, and the view from the windows is our project board, which is much less frightening than the drop.

And beneath it all sits the archive, the runbooks, the two postmortems, and the build log, because the structure is the achievement, but the record of how it was built is what lets us learn from it afterward.