Lesson 6.5 — Landing agent-written work¶
N branches that each passed alone have never been tested together.
TL;DR: Fan-out (6.3) multiplies the merge problem — N branches, each cleared its own adversarial
review (6.2) and Stop-gate (3.5) in isolation, that have never been integrated with each other or a
moving main. Per-diff gates are necessary but not sufficient: you also need an integration-level
gate on the combined result 1, a non-bypassable required-check policy 2, and a landing pass
that checks for the specific ways agent-generated PRs go wrong 3.
ELI5: everyone's essay was spell-checked, nobody read the whole book¶
Ten chapters, each proofread on its own, can still contradict each other — someone has to read the finished book.
Ten writers each spell-check their own chapter and every chapter passes. That tells you nothing about whether chapter 3 contradicts chapter 7, or whether two writers introduced the same character with different names. Passing your own check was never the same claim as the book being coherent. Landing agent-written work after fan-out is the same gap: per-diff review is the spell-check; you still need someone — or something — reading the whole book.
Per-diff gates aren't enough at fan-out¶
Each branch cleared its own gate in isolation — that says nothing about the combined result.
6.2's reviewer and 3.5's Stop-gate both operate on one diff. Fan out to N agents (6.3) and you get
N diffs that each individually pass — but none of them were ever tested against each other, or
against a main that kept moving while they worked. This isn't hypothetical: building a C compiler
with a fleet of parallel Claude agents, Anthropic hit exactly this failure mode late in the project —
Claude kept breaking existing functionality while implementing new features, because "for autonomous
systems, it is easy to see tests pass and assume the job is done, when this is rarely the case." The
fix was an integration-level CI pipeline with stricter enforcement so new commits couldn't break
existing code — a gate on the combined result, not just each agent's own claim 1.
flowchart TD
subgraph FANOUT["N agents fan out (6.3)"]
A1["agent A: diff A<br/>passes OWN review + Stop-gate"]
A2["agent B: diff B<br/>passes OWN review + Stop-gate"]
A3["agent C: diff C<br/>passes OWN review + Stop-gate"]
end
A1 --> INT
A2 --> INT
A3 --> INT
INT["INTEGRATION GATE<br/>full CI + e2e on the COMBINED result<br/>against current main"]
INT -->|"all pass together"| LAND["landing checklist (below)"]
INT -->|"any fail"| FIX["send back — the diffs<br/>never conflicted alone"]
LAND --> MERGE["merge — required checks<br/>cannot be bypassed"]
🧠 Test Yourself: Three agents each ship a diff that passes its own adversarial review and Stop-gate. Are you safe to merge all three?
Answer
Not necessarily. Each diff was validated in isolation against themainit branched from — not against the other two diffs, or againstmainas it stands now. You need an integration-level gate that runs the combined result 1.
Never bypass the gate¶
An admin-merge or force-merge is how a harness quietly stops meaning anything — and it's usually one unchecked setting away.
A required check only holds if nobody — including admins — can wave it through. GitHub's branch protection is explicit that this is opt-in, not the default: "the restrictions of a branch protection rule do not apply to people with admin permissions... You can enable this setting to apply the restrictions to admins... too" 2. If you've wired an integration gate but left admin bypass on, the gate is decorative for exactly the people most likely to reach for it under deadline pressure.
A rule of thumb: serialize singleton resources¶
Not every resource fans out safely — anything with exactly one current state (a migration chain, a config version) needs a rule, not just a gate.
Rule of thumb. Most work parallelizes cleanly because each agent's diff touches its own files. A singleton resource — a database migration chain being the classic case — doesn't: it has exactly one "current" state, and two agents each appending the next migration in parallel can produce a pair with no defined order. The practical fix is a norm, not a gate: serialize access to singleton resources (one migration PR lands, then the next agent generates against the new head), or make ordering explicit if your migration tool supports merge markers. This is repo discipline, not a documented industry standard — treat it as a starting heuristic, not doctrine.
The landing checklist¶
Borrow the read from someone who reviews agent PRs for a living — it isn't a merge-gate sequence, it's a reviewer's red-flag list, and that's still exactly what you need before landing fan-out work.
Before merging combined, integration-tested work, a human (or a scoped reviewer subagent) checks for the specific ways agent-generated PRs go wrong that generic CI doesn't catch 3:
| Red flag | What to check |
|---|---|
| CI gaming | Did coverage thresholds change, tests get removed, or a CI step get gated behind a new condition? "Any change that weakens CI is a blocker. Full stop." 3 |
| Hallucinated correctness | Does the PR include "a new test that fails on the pre-change behavior"? If the agent can't write a test that would have caught the bug it claims to fix, the fix is incomplete 3 |
| Code reuse blindness | For every new helper, a quick search — agents often duplicate an existing utility without recognizing it 3 |
| Agentic ghosting | Is the PR unresponsive to review comments? Request a breakdown before investing deep review time in a large, unresponsive proposal 3 |
| Untrusted input in workflows | Does anything in the change let untrusted content reach a prompt that then executes with elevated permissions? 3 |
🧠 Test Yourself: Two migrations from two different agents both pass CI individually. What repo-level rule catches the conflict a per-diff gate can't?
Answer
Serializing the singleton resource — the migration chain has exactly one current head, so the second agent must generate against the first agent's already-landed migration, not merge in parallel. This is a norm to enforce, not something either agent's own CI run could have caught alone.
Worked example¶
Same fan-out, two harnesses — one only gates the diff, one gates the landing.
Three agents each add a CSV-import feature to three different modules; each PR is reviewed, each Stop-gate is green.
- ❌ Diff-gated only: all three merge. Two of the three implemented near-identical CSV-parsing helpers with different edge-case handling — nobody searched for existing code before writing new code, and no integration test ever ran all three modules together. The duplication ships.
- ✅ Diff- and landing-gated: the integration gate runs the combined suite — still green, since the duplication itself doesn't break anything. But the landing checklist's code-reuse check flags two new near-identical helpers in the same PR wave, and a human consolidates them before merge.
Your turn (exercise)¶
Take the last batch of parallel/fan-out work you landed (or imagine one: 3 agents, 3 features). Write your own landing checklist as a literal markdown checklist — CI gaming, a new failing-before test present, no duplicate helpers, no unresponsive PRs sitting stale, no untrusted input reaching an elevated-permission prompt. Then check: is your required-status-check setting actually non-bypassable for admins? If you don't know, that's the first gap to close.
← Lesson 6.4 · next → Lesson 6.6 — Defining team direction
-
Building a C compiler with a team of parallel Claudes — Anthropic Engineering ↩↩↩
-
About protected branches — GitHub Docs ↩↩
-
Agent pull requests are everywhere. Here's how to review them. — GitHub Blog ↩↩↩↩↩↩↩