Agent Skills Framework Extension
Framework Migration Patterns Skill
When to Use This Skill
Use this skill when implementing framework migration patterns patterns in your codebase.
How to Use This Skill
- Review the patterns and examples below
- Apply the relevant patterns to your implementation
- Follow the best practices outlined in this skill
Production-grade framework upgrades, breaking change handling, and automated migrations.
Core Capabilities
- Version Analysis - Breaking change detection, deprecation tracking
- Automated Codemods - AST transformations for code updates
- Incremental Migration - Gradual rollout strategies
- Testing Strategies - Regression prevention during migration
- Rollback Plans - Safe migration with fallback options
Breaking Change Analysis
// tools/breaking_change_analyzer.rs
use semver::Version;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct BreakingChange {
pub version: Version,
pub description: String,
pub migration_guide: String,
pub affected_apis: Vec<String>,
pub automated_fix: Option<String>,
}
pub struct MigrationAnalyzer {
current_version: Version,
target_version: Version,
breaking_changes: Vec<BreakingChange>,
}
impl MigrationAnalyzer {
pub fn analyze(&self) -> MigrationPlan {
let applicable_changes: Vec<_> = self.breaking_changes
.iter()
.filter(|change| {
change.version > self.current_version &&
change.version <= self.target_version
})
.collect();
let total_changes = applicable_changes.len();
let automated_fixes = applicable_changes.iter()
.filter(|c| c.automated_fix.is_some())
.count();
MigrationPlan {
from_version: self.current_version.clone(),
to_version: self.target_version.clone(),
breaking_changes: applicable_changes.into_iter().cloned().collect(),
total_changes,
automated_fixes,
manual_changes: total_changes - automated_fixes,
estimated_effort_hours: self.estimate_effort(total_changes, automated_fixes),
}
}
fn estimate_effort(&self, total: usize, automated: usize) -> u32 {
let manual = total - automated;
(automated * 2 + manual * 8) as u32
}
}
#[derive(Debug)]
pub struct MigrationPlan {
pub from_version: Version,
pub to_version: Version,
pub breaking_changes: Vec<BreakingChange>,
pub total_changes: usize,
pub automated_fixes: usize,
pub manual_changes: usize,
pub estimated_effort_hours: u32,
}
Automated Codemod (JavaScript)
// codemods/upgrade-react-18.js
module.exports = function(fileInfo, api) {
const j = api.jscodeshift;
const root = j(fileInfo.source);
// Transform ReactDOM.render to createRoot
root
.find(j.CallExpression, {
callee: {
object: { name: 'ReactDOM' },
property: { name: 'render' }
}
})
.forEach(path => {
const [element, container] = path.value.arguments;
// Replace with createRoot API
const replacement = j.callExpression(
j.memberExpression(
j.callExpression(
j.memberExpression(
j.identifier('ReactDOM'),
j.identifier('createRoot')
),
[container]
),
j.identifier('render')
),
[element]
);
j(path).replaceWith(replacement);
});
// Update import statements
root
.find(j.ImportDeclaration, {
source: { value: 'react-dom' }
})
.forEach(path => {
const createRootSpecifier = j.importSpecifier(
j.identifier('createRoot')
);
if (!path.value.specifiers.some(s => s.imported?.name === 'createRoot')) {
path.value.specifiers.push(createRootSpecifier);
}
});
return root.toSource({ quote: 'single' });
};
Incremental Migration Strategy
// src/migration/incremental.rs
use std::collections::HashMap;
pub enum FeatureFlag {
UseNewApi,
UseOldApi,
}
pub struct FeatureFlagManager {
flags: HashMap<String, bool>,
}
impl FeatureFlagManager {
pub fn is_enabled(&self, flag: &str, user_id: &str) -> bool {
// Gradual rollout: 10% → 50% → 100%
let rollout_percentage = self.flags.get(flag).map(|_| 50).unwrap_or(0);
let hash = self.hash_user_id(user_id);
hash % 100 < rollout_percentage
}
fn hash_user_id(&self, user_id: &str) -> u32 {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
user_id.hash(&mut hasher);
(hasher.finish() % 100) as u32
}
}
// Example: Gradual API migration
pub async fn fetch_user_data(
user_id: &str,
feature_flags: &FeatureFlagManager
) -> Result<UserData, Error> {
if feature_flags.is_enabled("use_new_api", user_id) {
// New implementation
new_api::fetch_user(user_id).await
} else {
// Old implementation (fallback)
old_api::fetch_user(user_id).await
}
}
Migration Testing Strategy
// tests/migration_tests.rs
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_backward_compatibility() {
// Test that new code can read old data format
let old_data = r#"{"version": 1, "name": "test"}"#;
let parsed: UserData = serde_json::from_str(old_data).unwrap();
assert_eq!(parsed.name, "test");
assert_eq!(parsed.version, Some(1));
}
#[test]
fn test_forward_compatibility() {
// Test that old code can ignore new fields
let new_data = r#"{"version": 2, "name": "test", "new_field": "value"}"#;
let parsed: UserDataV1 = serde_json::from_str(new_data).unwrap();
// Old struct should ignore unknown fields
assert_eq!(parsed.name, "test");
}
#[tokio::test]
async fn test_dual_write() {
// Write to both old and new storage
let data = UserData::new("test");
old_storage::save(&data).await.unwrap();
new_storage::save(&data).await.unwrap();
// Verify consistency
let old_read = old_storage::load("test").await.unwrap();
let new_read = new_storage::load("test").await.unwrap();
assert_eq!(old_read, new_read);
}
}
Rollback Strategy
# .github/workflows/safe-migration.yml
name: Safe Migration Deployment
on:
push:
branches: [migration/v2]
jobs:
deploy-with-rollback:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy new version (canary)
run: |
kubectl set image deployment/myapp \
myapp=myapp:v2 \
-n production \
--record
- name: Monitor metrics
run: |
# Wait 5 minutes and check error rates
sleep 300
./scripts/check-metrics.sh
- name: Automatic rollback on failure
if: failure()
run: |
kubectl rollout undo deployment/myapp -n production
echo "Rollback triggered due to metrics failure"
Usage Examples
Analyze Migration
Apply framework-migration-patterns skill to analyze breaking changes from React 17 to React 18
Automated Codemod
Apply framework-migration-patterns skill to create codemod for API migration
Incremental Rollout
Apply framework-migration-patterns skill to implement gradual migration with feature flags
Success Output
When this skill is successfully applied, you MUST output:
✅ SKILL COMPLETE: framework-migration-patterns
Completed:
- [x] Breaking change analysis complete with migration plan
- [x] Automated codemods created for transformable changes
- [x] Incremental migration strategy implemented with feature flags
- [x] Testing strategy executed with backward compatibility verified
- [x] Rollback plan documented and tested
Outputs:
- Migration plan: [file path] (from_version → to_version, effort estimate)
- Codemods: [file paths] (automated transformations)
- Feature flag config: [file path] (gradual rollout)
- Test suite: [file path] (compatibility tests)
- Rollback procedure: [file path]
Completion Checklist
Before marking this skill as complete, verify:
- Breaking changes identified between current and target version
- Migration plan created with effort estimates (automated vs manual)
- Codemods written and tested for automated transformations
- Feature flags implemented for gradual rollout
- Backward compatibility tests passing
- Forward compatibility tests passing (old code ignores new fields)
- Dual-write strategy tested if applicable (write to old + new)
- Rollback plan documented with automatic rollback triggers
- Monitoring and metrics configured for migration health
Failure Indicators
This skill has FAILED if:
- ❌ Migration deployed without analysis of breaking changes
- ❌ Codemods produce incorrect transformations or break code
- ❌ All-at-once migration attempted without gradual rollout
- ❌ Backward compatibility broken (old data can't be read)
- ❌ Forward compatibility broken (new fields crash old code)
- ❌ No rollback plan or rollback fails when executed
- ❌ Migration causes production outage or data loss
- ❌ Manual changes required but not documented in migration guide
When NOT to Use
Do NOT use this skill when:
- Patch version upgrade with no breaking changes (standard dependency update)
- Framework not actually changing (configuration changes only)
- Migration scope too small to justify automation overhead (use manual update)
- Deprecated framework with no migration path (requires full rewrite, not migration)
- Internal tool with single developer (overhead > benefit)
Use alternatives:
- For patch updates: Standard
npm updateorcargo update - For full rewrites:
greenfield-architectureskill - For small manual changes: Direct code changes with review
- For config-only changes: Configuration management tools
Anti-Patterns (Avoid)
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Big-bang migration | All-at-once update causes wide outage | Incremental migration with feature flags |
| No automated codemods | Massive manual effort, error-prone | Write AST transformations for repetitive changes |
| Skipping compatibility tests | Runtime failures in production | Test backward and forward compatibility |
| No rollback plan | Stuck on broken version | Always have automated rollback procedure |
| Ignoring deprecation warnings | Sudden breaking changes | Track and address deprecations proactively |
| Over-automating edge cases | Codemod creates bugs | Automate common patterns, flag edge cases for manual review |
| No gradual rollout | Can't detect issues early | Use feature flags for 10% → 50% → 100% rollout |
| Missing migration guide | Manual steps undocumented | Create comprehensive guide for non-automated changes |
Principles
This skill embodies:
- #1 Recycle → Extend → Re-Use → Create - Leverage existing migration tools (codemods, feature flags)
- #2 First Principles - Understand WHY framework changed before migrating
- #8 No Assumptions - Verify compatibility, don't assume migration succeeded
- #9 Research When in Doubt - Check official migration guides and changelogs
- #11 Resilience and Robustness - Rollback plans and gradual rollout ensure stability
Full Standard: CODITECT-STANDARD-AUTOMATION.md
Migration Readiness Checklist
Pre-migration assessment to ensure successful upgrade:
| Category | Check | Status | Notes |
|---|---|---|---|
| Analysis | Breaking changes documented | ☐ | Review CHANGELOG, migration guide |
| Deprecation warnings addressed | ☐ | Run build, check warnings | |
| API changes mapped to codebase | ☐ | grep for deprecated APIs | |
| Testing | Test coverage >80% | ☐ | Run coverage report |
| Backward compatibility tests exist | ☐ | Old data format → new code | |
| Forward compatibility tests exist | ☐ | New data format → old code | |
| Automation | Codemods written for repetitive changes | ☐ | jscodeshift, ast-grep |
| CI/CD pipeline updated | ☐ | New build commands, deps | |
| Feature flags configured | ☐ | Gradual rollout ready | |
| Rollback | Rollback procedure documented | ☐ | kubectl rollout undo, etc |
| Rollback tested in staging | ☐ | Verify rollback works | |
| Monitoring alerts configured | ☐ | Error rate, latency thresholds | |
| Team | Team trained on new APIs | ☐ | Workshop, documentation review |
| Migration schedule communicated | ☐ | Stakeholder alignment |
Go/No-Go Decision:
All ☐ checked → ✅ Proceed with migration
Any ☐ unchecked → ⚠️ Address before proceeding
Effort Estimation Formula:
Hours = (automated_changes × 0.5) + (manual_changes × 4) + (testing × 8) + (rollback_prep × 4)
Integration Points
- cicd-automation-patterns - Automated migration deployment
- rust-development-patterns - Rust-specific migrations
- rust-qa-patterns - Migration testing