Next.js majors, Expo SDK bumps, React Native upgrades and Android targetSdk deadlines are the chores teams defer until they become emergencies. Run them instead as agentic loops where typecheck, tests and a production build form a deterministic harness the agent must satisfy before you review anything.
Tier: Core · Workflow area: Performance & debugging
This playbook turns a dreaded multi-day upgrade into a supervised loop: codemods handle the mechanical majority, the agent iterates on the ambiguous remainder, and the harness — not the agent's confidence — decides when it is done.
targetSdkVersion bump forced by a Play Console deadline, or an iOS deployment-target raise.Skip it for patch or minor bumps that pass CI untouched — merge those from your bot queue and move on.
typecheck, test and build all pass on the current version. An upgrade on a red baseline is unfalsifiable.npx @next/codemod), the React Native Upgrade Helper diff for your exact version pair, npx expo install --fix for Expo, and the Android behavior-changes page for your target API level.Freeze the harness before touching versions. Write the exact commands the loop must pass and record their green baseline output:
Before we upgrade anything, run these and confirm all pass:
1. npm run typecheck
2. npm test -- --ci
3. npm run build
Save the list of currently-skipped or known-flaky tests. During the
upgrade you may NOT skip, delete, or loosen any test or type to get
to green. If a test seems wrongly failing, stop and report it instead.
That no-loosening rule is the single most important sentence in the prompt.
Run the mechanical layer first, without the LLM. Codemods and helpers are deterministic; let them do the 80%: npx @next/codemod@latest upgrade for Next.js, the Upgrade Helper diff applied file-by-file for bare React Native, npx expo install --fix plus npx expo-doctor for Expo, and a targetSdk/AGP bump via Android Studio's AGP Upgrade Assistant. Commit this as its own "mechanical" commit so review can separate tool output from model output.
Hand the agent the residue as a loop. Now start the agentic pass:
The mechanical upgrade is committed. Run the harness. For each failure:
- Diagnose against the official migration guide (pasted below / linked).
- Fix the smallest surface that resolves it.
- Re-run the harness.
Work until all three commands pass. After each fix, append one line to
UPGRADE_LOG.md: what failed, why, what you changed. Ask me before any
change that alters runtime behavior rather than API shape.
Typical residue: renamed APIs the codemod missed, async request APIs in Next.js 15 (await cookies()), removed RN modules that moved to community packages, and Android manifest or permission changes for the new API level.
Chase behavior, not just compilation, on mobile. A targetSdk bump compiles clean while breaking runtime behavior (background limits, photo picker, exact alarms, foreground-service types). Ask the agent to cross-reference the behavior-changes page against your codebase:
Here is the Android 15 behavior-changes list. Grep the codebase for each
affected API or pattern and produce a table: change | files affected |
action needed | risk. Cite file:line for every row.
Verify on device and stage the release. Run the app — web: click the three most valuable flows; mobile: install a release build on a real device, cold start, background/foreground, deep link. Ship behind your normal staged rollout (10% Play rollout, phased App Store release) and watch crash rates for one interval before completing.
The agent never decides when the upgrade is done — the harness does. Your review effort goes to the UPGRADE_LOG.md diff between "mechanical" and "model" commits, which is where the risk lives.
git diff shows no added @ts-ignore, any, .skip, or deleted assertions).UPGRADE_LOG.md explains every non-mechanical change, and you spot-checked three entries against the official migration guide.targetSdk behavior table has an owner for every "action needed" row.targetSdk regressions are runtime-only; step 4 exists because the harness cannot see them.expo-doctor. Expo dependency mismatches surface as bizarre native crashes days later; run it every loop iteration.If policy forbids sending source to external APIs: run the codemod/upgrade-helper layer as normal (it is entirely local), then use an enterprise-tenancy assistant (Copilot Business, Bedrock-backed Claude) for the residue loop with the same frozen-harness prompt. With only a local model (Qwen-Coder-class via Ollama), shrink the loop: paste one failing error at a time with the relevant migration-guide section, and keep the harness runs manual.
Upgrade Helper diffs and behavior-changes pages are public — pasting them is safe. Your crash logs and file paths may not be; sanitize before using a chat tool outside your tenancy.
UPGRADE_LOG.md became the PR description, and reviewers approved without re-deriving the migration themselves.