Playbook
Migrations are where AI enthusiasm meets reality hardest. "Upgrade this to React 19," "move us from Express to Fastify," "get us onto the new ORM" — the agent dives in, rewrites forty files in one heroic pass, and hands you a diff that doesn't build, can't be reviewed, and can't be rolled back to a known-good point. Now you're not migrating; you're archaeology. The fix isn't a smarter agent. It's a method: small test-guarded steps, the build green between every one, and a checkpoint before each run so any step can be undone in seconds.
We migrate with agents regularly, and the ones that go smoothly all share the same shape. Here's the playbook.
Step 1 — Read the upgrade guide first
Before a single line changes, the agent reads the official migration or upgrade guide for the version or framework you're moving to — and summarizes the breaking changes that actually touch your code. This matters because the agent's training data remembers the old API; the guide has the new one and the exact renames, removals, and behavior changes. Skip this and the agent will confidently write code against the version it half-remembers, which is the version you're trying to leave. Have it produce a short list: what breaks, what's renamed, what's deprecated, and which of those your codebase actually uses.
Step 2 — Make it green before you start
You cannot migrate safely without a test suite that passes now, because that green suite is your only detector for "did this step break something." If coverage is thin around the code you're migrating, add tests first — see writing tests with AI that actually catch bugs. A migration with no tests is a rewrite you're doing blind; the tests are what turn each step from a leap into a check.
Step 3 — Slice into the smallest steps that build
The single biggest mistake is one giant pass. Instead, break the migration into the smallest units that each leave the build green: one module, one API surface, one deprecated call pattern at a time. After each slice: run the build, run the tests, confirm green, commit. A migration done in twenty small commits is reviewable and reversible; the same migration in one 2,000-line commit is neither. Tell the agent explicitly: change one coherent slice, get to green, stop, and let me confirm before the next.
Step 4 — Checkpoint before every run
Migrations fail mid-slice — the agent hits a case the guide didn't mention and starts thrashing. When that happens you want to be one command from a clean state, not untangling a half-applied change by hand. So take a checkpoint (a commit, a tag, or a worktree snapshot) before each slice runs. If the slice goes wrong, discard and retry from a known-good point instead of debugging the wreckage. This is exactly what checkpoints and worktrees exist for, and migrations are their best use case.
Step 5 — Write both directions for data migrations
If the migration touches the database schema, every change gets both an up and a down. The up applies the change; the down reverses it cleanly. Agents love to write the up and skip the down, which means the moment something's wrong in production you have no way back. Insist on both, and test the down by actually running it: apply, verify, roll back, verify the schema returned to its prior shape. A migration you can't reverse is a decision you can't unmake.
The step loop, as a table
| Per slice | What it guarantees | Order |
|---|---|---|
| Checkpoint before running | You can undo instantly | 1 |
| Apply one small change | Reviewable, reversible | 2 |
| Build + full tests | Nothing silently broke | 3 |
| Commit on green, then stop | A known-good point to build on | 4 |
The copy-paste migration prompt
We are migrating <from X> to <to Y>. Follow this method strictly.
1. Read the official upgrade guide for <Y>. List the breaking
changes that touch OUR code specifically: renames, removals,
behavior changes. Do not migrate from memory of the old API.
2. Confirm the test suite is green right now. If coverage is thin
around the affected code, add tests first and stop for my OK.
3. Migrate in the SMALLEST slices that keep the build green - one
module or one call pattern at a time. After each slice: run the
build and tests, paste real output, commit on green, then STOP
and wait for me before the next slice.
4. For any schema change, write BOTH the up and the down migration,
and test the down by actually rolling back.
Never make one large pass. Green between every step or we revert.
Choosing a model for the job
Migrations reward reasoning over speed — the hard part is untangling how the old and new APIs differ across your specific code. For a big, high-stakes framework migration, use your strongest model (Fable 5 leads our benchmarks at 95.0 SWE; Opus 4.8 for daily driving). For mechanical, repetitive slices — a deprecated call replaced the same way across fifty files — a fast, cheap model like Gemini Flash or DeepSeek runs the loop economically once you've verified the pattern on the first slice.
A migration is really a long chain of small changes, each of which needs the same discipline as any other: verify it, review it, and keep a green suite behind it. When a slice does break something, fixing bugs with AI applies, and a cross-model pass via the AI code review workflow catches the subtle behavior changes a migration hides. In The Vibe Father, checkpoints and git worktrees make "revert this slice" a single click and the AutoVibe gate re-runs your real build between steps — but the method above is just git commits and discipline, and it works anywhere.