Models love rewriting imports for the newest major. That is how you ship a tree that tsc loves and production hates. The unfair advantage is plan → matrix → rewrite: parse changelogs and lockfile diffs, run compatibility matrices across Node versions and peer ranges, then let the agent touch imports.
⚡ TL;DR: Freeze a machine-readable upgrade plan from
npm outdated/ changelog AST; execute matrix jobs (Node 20/22 × package peers); only then run AI codemods for import paths. Reject big-bang majors without matrix green. Pair with AST-Guided Edits and Node SDK Generation.
Upgrade plan as data
// deps/upgrade-plan.ts
export type UpgradeStep = {
name: string;
from: string;
to: string;
breaking: string[]; // parsed from CHANGELOG / # Breaking
peers: Record<string, string>;
codemod: "none" | "import_paths" | "api_rename";
};
export function assertOrdered(steps: UpgradeStep[]) {
// ✅ One major at a time for leaf packages first
const majors = steps.filter((s) => s.breaking.length);
if (majors.length > 3) throw new Error("too_many_majors_in_one_pr");
}
# Generate plan (illustrative)
node scripts/changelog-plan.mjs zod date-fns chalk > .upgrade/plan.json
# ❌ Don't: "upgrade everything in package.json to latest" as one agent prompt
Compatibility matrix before rewrites
# .github/workflows/dep-matrix.yml
strategy:
matrix:
node: [20, 22]
include:
- package: zod
peer: typescript@5.4
- package: zod
peer: typescript@5.6
steps:
- run: corepack enable && pnpm i --frozen-lockfile
- run: pnpm why ${{ matrix.package }}
- run: pnpm turbo run test typecheck --filter=...[origin/main]
Only when matrix cells are green do you allow the agent to emit import intents. Same gate philosophy as Spec-First AI Development.
Codemod after evidence
// After matrix green — structured intent, not freeform
const intent = {
kind: "replace_import",
target: { path: "src/**/*.ts", exportName: "z" },
payload: { from: "zod", to: "zod/v4" }, // example shape
};
// apply via ts-morph; typecheck again
| Stage | Owner | Stop condition |
|---|---|---|
| Plan | Bot + human | Unknown breaking notes |
| Matrix | CI | Any cell red |
| Rewrite | Agent | Typecheck/tests fail |
| Runtime canary | Platform | Error budget burn |
Closing checklist
✅ Dos
– ✅ Parse breaking sections into the plan
– ✅ Matrix Node × peers before import rewrites
– ✅ One major cluster per PR when possible
– ✅ Use AST intents for renames
– ✅ Canary runtime after merge
❌ Don’ts
– ❌ Don’t let the model bump majors and rewrite in one shot
– ❌ Don’t trust “compiles locally on Node 22” alone
– ❌ Don’t skip peer dependency conflicts
– ❌ Don’t rewrite lockfiles by hand in the agent
– ❌ Don’t merge without changelog citations in the PR
Related reading
- AST-Guided Edits: LLMs Propose Intents and Codemods Apply Them
- Node SDK Generation: OpenAPI-Driven Clients LLMs Cannot Hallucinate
- Spec-First AI Development: OpenAPI Remains the Only Source of Truth
- Cursor Agent Mode: Multi-File Refactors That Survive CI Gates
Last updated on September 11, 2026
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
