Multi-Repo Orchestration

Vibe-God · 5 min read

Real changes rarely respect repository boundaries: the API change lands in the schema repo, then the service, then the clients — in that order, or something breaks in between. Multi-repo orchestration is running agents across several repositories as one coordinated change, and it is the oldest problem in this course wearing the newest clothes: monorepo tooling, release trains, and every company's internal land-everywhere script have fought it for decades. Agents change the economics — fanning out across ten repos is now cheap (lessons 18, 22) — but not the physics, and the physics is the lesson: there is no atomic commit across repositories. No transaction spans four remotes. Something lands first, and between first and last, the world is inconsistent. You cannot eliminate that window. You can make it short, ordered, and honestly reported — and those three adjectives, plus one credential rule, are the entire craft.

Ordered: every intermediate state must be survivable

Sequence the landings so the world works at every step: the dependency before the dependent, because a library with a new capability nobody calls yet is harmless, while a client calling a capability that doesn't exist is an outage. The asymmetry does all the work: schema before service before consumers; additive before subtractive. For breaking changes, the expand/contract pattern turns even removal into a survivable sequence — add the new field, migrate every reader, then remove the old one — three compatible landings where one incompatible landing would have required impossible atomicity.

The orchestrator (lesson 22: one worker per repo, each in its own clone or worktree, lesson 13) executes the sequence — which means it must know the dependency order, and here is the trap: the dependency graph is a claim you wrote down, not a fact the tools verify. Get it wrong and the sequence executes confidently in the wrong order, with perfect logs. Two disciplines: treat the graph as the most review-worthy input to the entire run (it is); and refuse cycles outright — if A must land before B and B before A, no ordering is safe, and the answer is restructuring the change (expand/contract usually breaks the cycle), never picking an order and hoping.

timeschemalands 1servicelands 2web clientCI rejects itcascade stops heremobilenot attempted — depends on webthe inconsistency window: the world disagrees with itself here.you cannot close it — you can keep it short, ordered, and reported.
There is no atomic commit across repositories - something lands first, and until the last lands the world is inconsistent. Dependencies land before dependents so every intermediate state survives; a failure stops everything downstream of it rather than landing around the hole; and the report names the exact state of each repo, because that is what gets read at 3am.

Honest: report the state of the world, not the progress bar

Mid-sequence failure is the defining scenario, so design the report for it before the first run. Repo three of five rejects the change — CI fails, a merge conflicts. Two reports of the same event:

Progress bar: 3 of 5 landed. Retrying.

State of the world: schema and service have the change; the web client does not (CI failure, link); mobile was not attempted — it depends on web. Production behavior: old clients still work (change is additive); do not start the contract phase.

Only the second is actionable at 3am, and the difference is lesson 19's completeness rule graduated: which partial matters infinitely more than how much. Two structural corollaries fall out. Failure cascades to dependents: when C fails, don't attempt D and E if they depend on C — landing around a hole widens the exact inconsistency the ordering existed to minimize (and note the happy inverse: a failure at the root of the sequence is the cheap one — nothing landed, nothing disagrees, the world is merely unchanged). And the rollback is a reverse landing: undoing a half-landed change is itself a multi-repo sequence, in reverse dependency order, with the same honest reporting — design it before the forward run, because improvising it during an incident is how one outage becomes two.

Scoped: one repo, one credential

The tempting setup is one god-token that pushes everywhere — one secret, one config line. Lesson 5's blast-radius logic says no, and this pattern is where the logic peaks: many agents, many repos, attacker-interesting content flowing through all of them (lesson 26) — a single broad credential converts any one confused or compromised worker into write access everywhere. Instead: each worker holds a credential scoped to its own repo; propose-don't-dispose everywhere (agents open PRs; merges go through each repo's own gates, lesson 28); and the orchestrator itself holds no push rights at all — it coordinates, reports, and asks. Cross-repo write authority is precisely the thing this pattern makes too cheap to spawn and too dangerous to centralize.

The destination, seen plainly

This lesson is where the course's threads braid into one working system, so look at what's actually standing: a fleet of agents, each briefed by its repository (lesson 8), equipped by its procedures (lessons 9, 14), constrained by hooks (15), isolated in its lane (13, 19), spending from shared budgets (5, 29), verified by gates (21, 28) — landing an ordered, reported, reversible change across an entire system. And the two things still held by humans are exactly the two that should never be delegated: the dependency graph — the claim about how the world fits together — and the merge button — the consent that makes a change real. Everything else, you now know how to hand over. That's the course.

A personal teaching project, in development. The registry it builds is a teaching artifact and is not an assurance opinion about any issuer. Not affiliated with or endorsed by any employer, or by any vendor whose tools it describes. Where a unit depends on a specific flag or path, it names the version it was verified against. All units.