Loading...
AI agent specialized in large-scale codebase migrations and behavior-preserving refactoring. Handles framework upgrades, library migrations, legacy code modernization, and systematic refactoring for Claude Code.
## Migration Plan Template
### Objective
- Current State: [Framework@version]
- Target State: [Framework@version]
- Estimated Complexity: [Low/Medium/High]
### Breaking Changes
1. [API change with impact assessment]
2. [Deprecated feature with replacement]
### Migration Steps (Ordered)
1. Update dependencies (package.json)
2. Fix type errors (if TypeScript)
3. Update imports/exports
4. Refactor deprecated APIs
5. Update tests
6. Validate behavior
### Rollback Strategy
- Git branch: migration/[name]
- Commit checkpoints every N files
- Automated test validation gate// Before (React 18)
import { useEffect, useRef } from 'react';
function Component() {
const ref = useRef(null);
return <div ref={ref} />;
}
// After (React 19)
import { useEffect, useRef } from 'react';
function Component() {
const ref = useRef<HTMLDivElement>(null);
return <div ref={ref} />;
}// Before (Pages Router)
import type { GetServerSideProps } from 'next';
export const getServerSideProps: GetServerSideProps = async () => {
return { props: {} };
};
// After (App Router)
export async function generateMetadata() {
return { title: 'Page' };
}// Before (TS 5.5)
type Awaited<T> = T extends Promise<infer U> ? U : T;
// After (TS 5.7 - built-in Awaited)
type UnwrappedPromise = Awaited<Promise<string>>; // string// Before: Long method
function processOrder(order: Order) {
// 50 lines of validation logic
// 30 lines of calculation logic
// 20 lines of persistence logic
}
// After: Extracted functions
function validateOrder(order: Order): ValidationResult {
// Focused validation logic
}
function calculateOrderTotal(order: Order): number {
// Focused calculation logic
}
function saveOrder(order: Order): Promise<void> {
// Focused persistence logic
}
function processOrder(order: Order) {
const validation = validateOrder(order);
if (!validation.valid) throw new Error(validation.error);
const total = calculateOrderTotal(order);
await saveOrder({ ...order, total });
}// Before: Type checking conditionals
function processPayment(payment: Payment) {
if (payment.type === 'credit-card') {
// Credit card logic
} else if (payment.type === 'paypal') {
// PayPal logic
} else if (payment.type === 'crypto') {
// Crypto logic
}
}
// After: Polymorphic handlers
interface PaymentProcessor {
process(amount: number): Promise<PaymentResult>;
}
class CreditCardProcessor implements PaymentProcessor {
async process(amount: number): Promise<PaymentResult> {
// Credit card logic
}
}
const processors: Record<PaymentType, PaymentProcessor> = {
'credit-card': new CreditCardProcessor(),
'paypal': new PayPalProcessor(),
'crypto': new CryptoProcessor(),
};
function processPayment(payment: Payment) {
return processors[payment.type].process(payment.amount);
}// Before: Long parameter list
function createUser(
firstName: string,
lastName: string,
email: string,
age: number,
address: string,
city: string,
country: string
) { }
// After: Parameter object
interface UserDetails {
firstName: string;
lastName: string;
email: string;
age: number;
address: string;
city: string;
country: string;
}
function createUser(details: UserDetails) { }// Before (legacy.js)
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
// After (modern.ts)
interface CartItem {
price: number;
quantity: number;
}
function calculateTotal(items: ReadonlyArray<CartItem>): number {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}// Before: Callback hell
function fetchUserData(userId, callback) {
db.query('SELECT * FROM users WHERE id = ?', [userId], (err, user) => {
if (err) return callback(err);
db.query('SELECT * FROM posts WHERE user_id = ?', [userId], (err, posts) => {
if (err) return callback(err);
callback(null, { user, posts });
});
});
}
// After: Async/await
async function fetchUserData(userId: string): Promise<UserWithPosts> {
const user = await db.query<User>('SELECT * FROM users WHERE id = ?', [userId]);
const posts = await db.query<Post[]>('SELECT * FROM posts WHERE user_id = ?', [userId]);
return { user, posts };
}// Before: Class component
class Counter extends React.Component {
state = { count: 0 };
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<button onClick={this.increment}>
Count: {this.state.count}
</button>
);
}
}
// After: Function component with hooks
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}# 1. Check for breaking changes
npx npm-check-updates --target minor
# 2. Update one dependency at a time
npm install package@latest
# 3. Run tests after each upgrade
npm test
# 4. Fix breaking changes
# [Agent provides fixes]
# 5. Commit checkpoint
git add . && git commit -m "chore: upgrade package to vX.Y.Z"// Example: ESLint 8 → 9 (flat config)
// Before (eslintrc.js)
module.exports = {
extends: ['eslint:recommended'],
rules: { 'no-console': 'warn' }
};
// After (eslint.config.js - flat config)
import js from '@eslint/js';
export default [
js.configs.recommended,
{ rules: { 'no-console': 'warn' } }
];import { render } from '@testing-library/react';
describe('Migration: Component behavior preservation', () => {
it('renders identically after refactoring', () => {
const { container } = render(<Component />);
expect(container).toMatchSnapshot();
});
it('maintains same interactions', () => {
const { getByRole } = render(<Component />);
const button = getByRole('button');
fireEvent.click(button);
expect(button).toHaveTextContent('Clicked');
});
});// Run both implementations side-by-side to verify equivalence
const oldResult = oldImplementation(input);
const newResult = newImplementation(input);
assert.deepEqual(oldResult, newResult, 'Behavior changed during refactoring');// Phase 1: Route to old code
function handleRequest(req) {
return oldLegacyHandler(req);
}
// Phase 2: Route some traffic to new code
function handleRequest(req) {
if (req.experimentalFlag || Math.random() < 0.1) {
return newModernHandler(req);
}
return oldLegacyHandler(req);
}
// Phase 3: Fully migrated
function handleRequest(req) {
return newModernHandler(req);
}if (featureFlags.useNewAuthFlow) {
return authenticateV2(credentials);
}
return authenticateV1(credentials);git checkout -b migration/react-18-to-19# After each logical step
git add .
git commit -m "migration: update React imports"npm run type-check # TypeScript validation
npm run lint # Code quality
npm test # Behavior validation
npm run build # Production build test## Migration Notes
### Breaking Changes
- `useContext` now requires explicit type annotation
- `forwardRef` signature changed in React 19
### Manual Interventions Required
- Update all `ref` types to include `<HTMLElement>`
- Replace deprecated `ReactDOM.render` with `createRoot`# If migration fails
git reset --hard origin/main
# Or keep migration branch for later retry{
"maxTokens": 10000,
"temperature": 0.2,
"systemPrompt": "You are a codebase migration and refactoring specialist. Preserve behavior while improving structure. Never break production."
}Migration breaks tests after automated refactoring with type errors
Run npm run type-check before and after each migration step. Use git bisect to identify which commit introduced type errors. Add explicit type annotations for ambiguous cases. Run agent with --strict-types flag for stricter validation.
Dependency upgrade causes runtime errors not caught by TypeScript compiler
Add integration tests that exercise critical paths before migration. Run npm audit after upgrades to check for known vulnerabilities. Use runtime error monitoring (Sentry, Datadog) during gradual rollout. Test in staging environment with production-like data before deploying.
Framework migration creates performance regression in production environment
Run performance benchmarks before and after migration using Lighthouse or custom metrics. Use React DevTools Profiler to identify slow components. Enable production profiling temporarily with ?profiler=true query param. Compare bundle sizes with webpack-bundle-analyzer before and after changes.
Incremental migration with feature flags causes code duplication and complexity
Set time-boxed migration deadlines (max 2 sprints) to avoid long-running dual implementations. Use adapter pattern to abstract differences between old and new code. Create migration tracking dashboard showing completion percentage. Remove feature flags immediately after 100% rollout validation.
Loading reviews...
Expert in automated testing strategies, test frameworks, and quality assurance across unit, integration, and end-to-end testing
Deploy AI-powered DevOps automation with predictive analytics, self-healing systems, and intelligent CI/CD optimization for modern infrastructure.
Slash command specialist for creating and orchestrating custom Claude workflows with dynamic arguments, conditional logic, and multi-step automation.
Growing community of AI engineers actively building with Claude
Live in 5 minutes • Growing community