Verification Capital

The Coordination Platform You Don't Need

The obvious tool was sitting right there. Claude Code and Codex, two coding agents run by the same operator, needed a way to hand work to each other, and their shared toolkit already included a dedicated handoff mechanism built for what looked like exactly this. Then a live check of the tool's actual schema came back, and the obvious answer turned out to be a locked door with a welcome mat. Authoring a handoff through it was gated to one specific caller: Claude Code and Codex could not author a peer handoff through it at all. Pickup was asymmetric too. One agent could confirm and take a handoff; the other was refused until promoted to a higher trust level. As a peer channel, the dedicated dispatch tool was a hierarchy wearing a friendly name.

That is a security or trust-model fact, so I will state it straight: the gates were real, deliberate, and doing their job. Which left two options. Option one, re-engineer the trust model so both agents could use the dispatch tool as equals. This is the option that feels like progress, and the version of me that almost took it was already sketching the caller-promotion logic. It was rejected, because it fights the system's own security model and the cost is high. You do not loosen a trust boundary because it is inconvenient for a workflow you invented last week.

Option two was to look around. And here is the part I keep coming back to: a fully symmetric coordination surface already existed, was in constant daily use, and had escaped notice because it was filed under the least glamorous name in the entire system. Activity logging. The general-purpose log (log_activity and its siblings) has no caller gate at all. Either agent can write to it, either agent can read it, and they already did, constantly. On the same day this was checked, Codex alone had written 8 activity-log entries carrying branch names in a single work window. The peer channel was not missing. It was busy.

The contract that was already free

One month ago, these two agents had no shared operating contract. Today a single 8-rule doctrine governs both, adopted in one canonical location, with one-line pointers from each agent's own configuration, never copies. And the mechanical core of that doctrine is almost embarrassingly small: a peer handoff is the git branch as the lock, plus a symmetric activity-log receipt. Deliberately routed away from the one gated, asymmetric dispatch tool that looked like the obvious answer.

No lease database. No lock files. No expiry daemon. The lock is a branch that either exists on origin or does not; the descriptor rides a plain 8-line receipt. Both artifacts were things the agents already had.

The 8 rules, ratified after a live pilot:

  1. Peers, not owners.
  2. One task, one writer.
  3. The workspace (a branch) is the lease.
  4. Declare before you write (run the preflight).
  5. Prove what you did (the receipt).
  6. Takeover is snapshot-first and ack-free (no live holder required to release).
  7. Ceremony scales with blast radius (a single-file edit needs none; shared-state work needs the full ritual).
  8. Preserve first, fix second (rescue a reference before any recovery move; never reset a shared ref).

Rule 1 is the thesis and rule 5 is the enforcement, but the whole list runs on ordinary git plumbing and a text note. The doctrine is less a platform than a table manner.

Proving symmetry with bytes

A doctrine that says "peers" can still hide a hierarchy in its ceremony, so the ratification was a live, operator-mediated drill in a disposable sandbox: three tasks.

Task 1, Codex to Claude Code: Claude Code took over from a 5-field receipt alone, zero questions, and the diff matched exactly. Task 2, Claude Code to Codex: Codex took over from the receipt alone, zero questions, verified clean. These two are the real proof of peerhood, and the reason is what they do not contain. They are the same ceremony with the same friction, which is to say zero, in both directions. A hierarchy would show up as one direction needing more ritual than the other. It did not.

Task 5 was a deliberate collision, and it carries the harder claim: that branch-as-lease actually stops a second writer, rather than merely describing one. Claude Code preflighted clean and claimed the lease. Codex preflighted, saw the occupied branch, and refused. The filesystem confirmed a single writer and no divergent branch. Not a claim about a receipt; the receipt itself.

The gap the pilot refused to hide

The pilot's own disposition declined to call itself clean, which is the kind of sentence I enjoy writing more than I enjoyed reading it at the time. Task 5 ran in a shared working tree, where Codex could see Claude Code's checked-out branch directly. Easy-mode detection. The harder, realistic case for real automation is two agents in separate clones, each creating the same task branch before either pushes. That case was explicitly flagged as undrilled, and automation was gated on drilling it.

The drill ran the next day, on a disposable rig: a bare origin plus two clones, the base branch named trunk to dodge a push-to-main guard. It reproduced the gap exactly. Without a git fetch, a second clone's local branch creation does not collide. It succeeds, silently, and the collision surfaces only at push time as a non-fast-forward, where git's own hint suggests pull or --force, both of which would corrupt the one-writer invariant. Git, faced with two writers, helpfully offers two ways to make it worse.

With a mandatory fetch plus a remote-lease check before any write, the second agent detects the held branch and refuses cleanly, with zero divergent work created. So the doctrine's preflight step was rewritten. It had said "fetch if another agent may hold it," which is a judgment call. It now says "fetch, always, mandatory," which is a machine-checkable rule. A soft guideline could not close this gap, because you cannot know whether a branch is held without checking. The judgment call was asking the agent to already have the information the fetch exists to provide.

From ritual to program

Enforcement then became executable primitives rather than disciplinary prose, in a small published repo of enforcement primitives: a shell preflight gate and a Python dispatcher. The gate turns the closed-gap preflight into a single check (fetch, remote-lease check, local-lease check, dirty-tree check) returning CLAIM, REFUSE, or ERROR. The dispatcher runs that gate before letting any agent write, in one of two modes: a relay mode, the default, which prints an operator-facing dispatch packet and stays human-mediated, and a spawn mode, which launches the writer directly and then verifies completion on the git bytes, commits ahead of base and pushed to origin, never trusting the agent's exit code.

That verify-on-bytes discipline is not paranoia for its own sake. It encodes an earlier lesson from the same month, when a stranded handoff reported itself "completed" while its work sat uncommitted and unreceipted. The dispatcher treats that exact failure as a first-class branch of its state machine, not an edge case. The agent's word is an input; the bytes are the answer.

Notice what all this tooling is for. The gate, the dispatcher, the verification pass: none of it invents new coordination machinery. Every line exists to enforce a convention that was already free. The sophistication came after the simplicity, in service of it.

Where the proof layer bent

The doctrine's proof rule says "reports without receipts are not proof," and that rule got tested against real execution volume, not just the pilot. It did not hold. Receipts slipped on three of the last five handoffs, including two where the spec explicitly demanded one. The work itself was always real, verified against the branches independently every time. The proof layer, not the work, was unreliable: it held about 60% of the time under load, on a stable, explicit rule.

The response was not to ask harder. It was to build an automated grader the same week: a harness-scorecard check that grades, and does not block, any peer-agent branch that is commits-ahead of main with no matching receipt. It shipped, went live in both harness suites, and immediately flagged other real unreceipted branches elsewhere. That last part matters, because it means the check grades live drift rather than a synthetic test case. The receipt rule failed as a norm and got rebuilt as an instrument, which is the same trajectory the preflight took: every rule in this doctrine that survived contact with real load did so by becoming a program.

The platform, itemized

Here is the complete bill of materials for turning two gated, asymmetric agents into true peers. A git branch, which either exists on origin or does not. An 8-line plain text receipt, written to an activity log both agents could already use. A preflight that fetches, always, mandatory. And a grader that notices when the note is missing.

That is the whole platform. No service was stood up. No daemon watches for expired leases, because there are no leases to expire, only branches to fetch. The dedicated coordination tool sits exactly where it was, gated exactly as designed, politely routed around.

The scope matters. This is not an argument against coordination services for low-trust, multi-tenant, external, or heterogeneous agents. It is an argument about two trusted peer agents under one operator, sharing git, sharing a log, and already leaving receipts in the same local operating layer. The method was not anti-platform minimalism. It was platform growth from receipts of failure: a missed fetch became a preflight gate, missing notes became a grader, and each new primitive earned its place by closing a failure the previous ritual had already exposed.

The lesson I would actually hand to someone building a multi-agent setup is not "use git," although, use git. It is this: before you design the coordination layer, inventory the symmetric surfaces you already have, especially the ones with boring names, because boring names are where symmetric surfaces go to be ignored. Somewhere in your system there is probably a channel with no caller gate, in constant daily use, holding eight entries with branch names in them from this morning.

Check the boring name first. The coordination platform these two agents almost built was a branch and a plain text note the whole time.

Postscript, 2026-07-11

The receipt rule kept hardening after this published. The correction-by-narration habit that plagues the shared store got a schema of its own: closeout receipts now supersede prior claims by structured record, the superseded entry's ID and a content hash bound into the new row, instead of a prose "ignore what I said earlier." Norm, then instrument, then schema. Every rule in this doctrine that survives contact with real load seems to walk the same road, one failure at a time.

Adjacent reading