Migrate Operations
Comprehensive migration skill covering framework upgrades, language version bumps, dependency auditing, breaking change detection, codemods, and rollback strategies.
Ecosystem facts verified as of 2026-07-05.
Migration Strategy Decision Tree
What kind of migration are you performing?
│
├─ Small library update (patch/minor version)
│ └─ In-place upgrade
│ Update dependency, run tests, deploy
│
├─ Major framework version (React 18→19, Vue 2→3, Laravel 12→13)
│ │
│ ├─ Codebase < 50k LOC, good test coverage (>70%)
│ │ └─ Big Bang Migration
│ │ Upgrade everything at once in a feature branch
│ │ Pros: clean cutover, no dual-version complexity
│ │ Cons: high risk, long branch life, merge conflicts
│ │
│ ├─ Codebase > 50k LOC, partial test coverage
│ │ └─ Incremental Migration
│ │ Upgrade module by module, use compatibility layers
│ │ Pros: lower risk per step, continuous delivery
│ │ Cons: dual-version code, longer total duration
│ │
│ ├─ Monolith → microservice or complete architecture shift
│ │ └─ Strangler Fig Pattern
│ │ Route new features to new system, migrate old features gradually
│ │ Pros: zero-downtime, reversible, production-validated
│ │ Cons: routing complexity, data sync challenges
│ │
│ └─ High-risk data pipeline or financial system
│ └─ Parallel Run
│ Run old and new systems simultaneously, compare outputs
│ Pros: highest confidence, catch subtle differences
│ Cons: double infrastructure cost, comparison logic
│
└─ Language version upgrade (Python 3.12→3.14, Node 22→26)
└─ In-place upgrade with CI matrix
Test against both old and new versions in CI
Drop old version support once all tests pass
Framework Upgrade Decision Tree
Which framework are you upgrading?
│
├─ React 18 → 19
│ ├─ Check: Remove forwardRef wrappers (ref is now a regular prop)
│ ├─ Check: Replace <Context.Provider> with <Context>
│ ├─ Check: Adopt useActionState / useFormStatus for forms
│ ├─ Check: Replace manual memoization if using React Compiler
│ ├─ Codemod: npx codemod@latest react/19/migration-recipe
│ └─ Load: ./references/framework-upgrades.md
│
├─ Next.js Pages Router → App Router
│ ├─ Check: Move pages/ to app/ with new file conventions
│ ├─ Check: Replace getServerSideProps/getStaticProps with async components
│ ├─ Check: Convert _app.tsx and _document.tsx to layout.tsx
│ ├─ Check: Update data fetching to use fetch() with caching options
│ ├─ Codemod: npx @next/codemod@latest
│ └─ Load: ./references/framework-upgrades.md
│
├─ Vue 2 → 3
│ ├─ Check: Replace Options API with Composition API (optional but recommended)
│ ├─ Check: Replace Vuex with Pinia
│ ├─ Check: Replace event bus with mitt or provide/inject
│ ├─ Check: Update v-model syntax (modelValue prop)
│ ├─ Tool: Migration build (@vue/compat) for incremental migration
│ └─ Load: ./references/framework-upgrades.md
│
├─ Laravel 12 → 13
│ ├─ Check: PHP 8.3 is now the minimum (8.5 supported)
│ ├─ Check: Cache/Redis key prefixes now use hyphenated suffixes
│ ├─ Check: Adopt native PHP attributes (models, jobs, controllers) — optional
│ ├─ Check: Queue routing by class via Queue::route(...) — optional
│ ├─ Tool: laravel shift (automated upgrade service)
│ └─ Load: ./references/framework-upgrades.md (covers 10→11 in depth; 12→13 is near zero-break)
│
├─ Angular (any major version)
│ ├─ Check: Run ng update for guided migration
│ ├─ Check: Review Angular Update Guide (update.angular.io)
│ ├─ Tool: ng update @angular/core @angular/cli
│ └─ Load: ./references/framework-upgrades.md
│
└─ Django (any major version)
├─ Check: Run python -Wd manage.py test for deprecation warnings
├─ Check: Review Django release notes for removals
├─ Tool: django-upgrade (automatic fixer)
└─ Load: ./references/framework-upgrades.md
Dependency Audit Workflow
Ecosystem?
│
├─ JavaScript / Node.js
│ ├─ npm audit / npm audit fix
│ ├─ npx audit-ci --moderate (CI integration)
│ └─ Socket.dev for supply chain analysis
│
├─ Python
│ ├─ pip-audit
│ ├─ safety check
│ └─ pip-audit --fix (auto-update vulnerable packages)
│
├─ Rust
│ ├─ cargo audit
│ └─ cargo deny check advisories
│
├─ Go
│ ├─ govulncheck ./...
│ └─ go list -m -u all (list available updates)
│
├─ PHP
│ ├─ composer audit
│ └─ composer outdated --direct
│
└─ Multi-ecosystem
└─ Trivy, Snyk, or Dependabot across all
Pre-Migration Checklist
[ ] Test coverage measured and documented (target: >70% for critical paths)
[ ] CI pipeline green on current version
[ ] All dependencies up to date (or pinned with rationale)
[ ] Database backup taken (if applicable)
[ ] Git state clean — migration branch created from latest main
[ ] Rollback plan documented and tested
[ ] Breaking change list reviewed from upstream changelog
[ ] Team notified of migration window
[ ] Feature flags in place for gradual rollout (if applicable)
[ ] Monitoring and alerting configured for regression detection
[ ] Performance baseline captured (response times, memory, CPU)
[ ] Lock file committed (package-lock.json, yarn.lock, Cargo.lock, etc.)
Breaking Change Detection Patterns
How do you detect breaking changes?
│
├─ Semver Analysis
│ ├─ Major version bump → breaking changes guaranteed
│ ├─ Check CHANGELOG.md or BREAKING_CHANGES.md in repo
│ └─ npm: npx npm-check-updates --target major
│
├─ Changelog Parsing
│ ├─ Search for: "BREAKING", "removed", "deprecated", "renamed"
│ ├─ GitHub: compare releases page between versions
│ └─ Read migration guide if one exists
│
├─ Compiler / Runtime Warnings
│ ├─ Enable all deprecation warnings before upgrading
│ ├─ Python: python -Wd (turn deprecation warnings to errors)
│ ├─ Node: node --throw-deprecation
│ └─ TypeScript: strict mode catches type-level breaks
│
├─ Codemods (automated detection + fix)
│ ├─ jscodeshift — JavaScript/TypeScript AST transforms
│ ├─ ast-grep — language-agnostic structural search/replace
│ ├─ rector — PHP automated refactoring
│ ├─ gofmt / gofumpt — Go formatting changes
│ └─ 2to3 — Python 2 to 3 (legacy)
│
└─ Type Checking
├─ TypeScript: tsc --noEmit catches API shape changes
├─ Python: mypy / pyright after upgrade
└─ Go: go vet ./... after upgrade
Codemod Quick Reference
| Ecosystem |
Tool |
Command |
Use Case |
| JS/TS |
jscodeshift |
npx jscodeshift -t transform.ts src/ |
Custom AST transforms |
| JS/TS |
ast-grep |
sg --pattern 'old($$$)' --rewrite 'new($$$)' |
Structural find/replace |
| React |
react-codemod |
npx codemod@latest react/19/migration-recipe |
React version upgrades |
| Next.js |
next-codemod |
npx @next/codemod@latest |
Next.js version upgrades |
| Vue |
vue-codemod |
npx @vue/codemod src/ |
Vue 2 to 3 transforms |
| PHP |
Rector |
vendor/bin/rector process src |
PHP version + framework upgrades |
| Python |
pyupgrade |
pyupgrade --py314-plus *.py |
Python version syntax upgrades |
| Python |
django-upgrade |
django-upgrade --target-version 5.0 *.py |
Django version upgrades |
| Go |
gofmt |
gofmt -w . |
Go formatting updates |
| Go |
gofix |
go fix ./... |
Go API changes |
| Rust |
cargo fix |
cargo fix --edition |
Rust edition migration |
| Multi |
ast-grep |
sg scan --rule rules.yml |
Any language with custom rules |
Rollback Strategy Decision Tree
Migration failed or caused issues — how to roll back?
│
├─ Code-only change, no data migration
│ ├─ Small number of commits
│ │ └─ Git Revert
│ │ git revert --no-commit HEAD~N..HEAD && git commit
│ │ Pros: clean history, safe for shared branches
│ │ Cons: merge conflicts if code has diverged
│ │
│ └─ Entire feature branch
│ └─ Revert merge commit
│ git revert -m 1 <merge-commit-sha>
│
├─ Feature flag controlled
│ └─ Toggle flag off
│ Instant rollback, no deployment needed
│ Keep old code path until new path is proven
│
├─ Database schema changed
│ ├─ Reversible migration exists
│ │ └─ Run down migration
│ │ rails db:rollback / php artisan migrate:rollback / alembic downgrade
│ │
│ └─ Irreversible migration (dropped column, changed type)
│ └─ Restore from backup + replay write-ahead log
│ This is why you take backups BEFORE migration
│
└─ Infrastructure / deployment
├─ Blue-Green deployment
│ └─ Switch traffic back to blue (old) environment
│
├─ Canary deployment
│ └─ Route 100% traffic back to stable version
│
└─ Container orchestration (K8s)
└─ kubectl rollout undo deployment/app
Common Gotchas
| Gotcha |
Why It Happens |
Prevention |
| Upgrading multiple major versions at once |
Each major version may have sequential breaking changes that compound |
Upgrade one major version at a time, verify, then proceed |
| Lock file not committed before migration |
Cannot reproduce pre-migration dependency state |
Always commit lock files; take a snapshot branch before starting |
| Running codemods without committing first |
Cannot diff what the codemod changed vs your manual changes |
Commit clean state, run codemod, commit codemod changes separately |
| Ignoring deprecation warnings in current version |
Deprecated APIs are removed in next major version |
Fix all deprecation warnings BEFORE upgrading |
| Testing only happy paths after migration |
Edge cases and error paths are most likely to break |
Run full test suite plus manual exploratory testing |
| Not checking transitive dependencies |
A direct dep upgrade may pull in incompatible transitive deps |
Use npm ls, pip show, cargo tree to inspect dependency tree |
| Assuming codemods catch everything |
Codemods handle common patterns, not all patterns |
Review codemod output manually; check for skipped files |
| Skipping the migration guide |
Framework authors document known pitfalls and workarounds |
Read the official migration guide end-to-end before starting |
| Migrating in a long-lived branch |
Main branch diverges, causing painful merge conflicts |
Use feature flags for incremental migration on main |
| Not updating CI to test both versions |
CI passes on old version but new version has failures |
Add matrix testing for both versions during transition |
| Database migration without backup |
Irreversible schema changes with no recovery path |
Always backup before migration; test rollback procedure |
| Forgetting to update Docker/CI base images |
Code upgraded but runtime is still old version |
Update Dockerfile FROM, CI config, and deployment manifests |
Reference Files
| File |
Contents |
Lines |
references/framework-upgrades.md |
React 18→19, Next.js Pages→App Router, Vue 2→3, Laravel 10→13, Angular, Django upgrade paths |
~700 |
references/language-upgrades.md |
Python 3.9→3.14, Node 18→26, TypeScript 4→6, Go 1.20→1.26, Rust 2021→2024, PHP 8.1→8.5 |
~650 |
references/dependency-management.md |
Audit tools, update strategies, lock files, monorepo deps, supply chain security |
~550 |
Staleness verifier
This skill hardcodes specific framework/language target versions (React 19, Laravel 13, Python 3.14, Node 26, TypeScript 6, Go 1.26, Rust 2024, PHP 8.5). scripts/check-migrate-facts.py guards them against silent drift:
# Structural (PR CI, no network): every catalogued target version still appears
# where it is recorded (description vs body), and the currency note carries a year.
python scripts/check-migrate-facts.py --offline # exit 0 consistent, 10 drift
# Live (freshness job, never blocks a PR): each target is resolved against
# endoflife.date (python/nodejs/laravel/php/go) and npm (react/typescript).
python scripts/check-migrate-facts.py --live # exit 10 a target lags latest, 7 unreachable
The canonical target-version list lives in assets/migrate-facts.json; when you change a recommended target, update it to match or --offline fails CI. A --live drift means the skill is naming an older target than the ecosystem's current stable — review, don't auto-rewrite.
See Also
| Skill |
When to Combine |
testing-ops |
Ensuring test coverage before migration, writing regression tests after |
debug-ops |
Diagnosing failures introduced by migration, bisecting breaking commits |
git-ops |
Branch strategy for migration, git bisect to find breaking change |
refactor-ops |
Code transformations that often accompany version upgrades |
ci-cd-ops |
Updating CI pipelines to test against new versions, matrix builds |
container-orchestration |
Updating base images, Dockerfile changes for new runtime versions |
security-ops |
Vulnerability remediation that triggers dependency upgrades |
1---2name: migrate-ops3description: Framework and language migration patterns - version upgrades, breaking changes, dependency audit, safe rollback. Use for: migrate, migration, upgrade, version bump, breaking changes, deprecation, dependency audit, npm audit, pip-audit, codemod, jscodeshift, rector, rollback, semver, changelog, framework upgrade, language upgrade, React 19, Vue 3, Next.js App Router, Laravel 13, Angular, Python 3.14, Node 26, TypeScript 6, Go 1.26, Rust 2024, PHP 8.5.4license: MIT5---67# Migrate Operations89Comprehensive migration skill covering framework upgrades, language version bumps, dependency auditing, breaking change detection, codemods, and rollback strategies.1011> Ecosystem facts verified as of 2026-07-05.1213## Migration Strategy Decision Tree1415```16What kind of migration are you performing?17│18├─ Small library update (patch/minor version)19│ └─ In-place upgrade20│ Update dependency, run tests, deploy21│22├─ Major framework version (React 18→19, Vue 2→3, Laravel 12→13)23│ │24│ ├─ Codebase < 50k LOC, good test coverage (>70%)25│ │ └─ Big Bang Migration26│ │ Upgrade everything at once in a feature branch27│ │ Pros: clean cutover, no dual-version complexity28│ │ Cons: high risk, long branch life, merge conflicts29│ │30│ ├─ Codebase > 50k LOC, partial test coverage31│ │ └─ Incremental Migration32│ │ Upgrade module by module, use compatibility layers33│ │ Pros: lower risk per step, continuous delivery34│ │ Cons: dual-version code, longer total duration35│ │36│ ├─ Monolith → microservice or complete architecture shift37│ │ └─ Strangler Fig Pattern38│ │ Route new features to new system, migrate old features gradually39│ │ Pros: zero-downtime, reversible, production-validated40│ │ Cons: routing complexity, data sync challenges41│ │42│ └─ High-risk data pipeline or financial system43│ └─ Parallel Run44│ Run old and new systems simultaneously, compare outputs45│ Pros: highest confidence, catch subtle differences46│ Cons: double infrastructure cost, comparison logic47│48└─ Language version upgrade (Python 3.12→3.14, Node 22→26)49 └─ In-place upgrade with CI matrix50 Test against both old and new versions in CI51 Drop old version support once all tests pass52```5354## Framework Upgrade Decision Tree5556```57Which framework are you upgrading?58│59├─ React 18 → 1960│ ├─ Check: Remove forwardRef wrappers (ref is now a regular prop)61│ ├─ Check: Replace <Context.Provider> with <Context>62│ ├─ Check: Adopt useActionState / useFormStatus for forms63│ ├─ Check: Replace manual memoization if using React Compiler64│ ├─ Codemod: npx codemod@latest react/19/migration-recipe65│ └─ Load: ./references/framework-upgrades.md66│67├─ Next.js Pages Router → App Router68│ ├─ Check: Move pages/ to app/ with new file conventions69│ ├─ Check: Replace getServerSideProps/getStaticProps with async components70│ ├─ Check: Convert _app.tsx and _document.tsx to layout.tsx71│ ├─ Check: Update data fetching to use fetch() with caching options72│ ├─ Codemod: npx @next/codemod@latest73│ └─ Load: ./references/framework-upgrades.md74│75├─ Vue 2 → 376│ ├─ Check: Replace Options API with Composition API (optional but recommended)77│ ├─ Check: Replace Vuex with Pinia78│ ├─ Check: Replace event bus with mitt or provide/inject79│ ├─ Check: Update v-model syntax (modelValue prop)80│ ├─ Tool: Migration build (@vue/compat) for incremental migration81│ └─ Load: ./references/framework-upgrades.md82│83├─ Laravel 12 → 1384│ ├─ Check: PHP 8.3 is now the minimum (8.5 supported)85│ ├─ Check: Cache/Redis key prefixes now use hyphenated suffixes86│ ├─ Check: Adopt native PHP attributes (models, jobs, controllers) — optional87│ ├─ Check: Queue routing by class via Queue::route(...) — optional88│ ├─ Tool: laravel shift (automated upgrade service)89│ └─ Load: ./references/framework-upgrades.md (covers 10→11 in depth; 12→13 is near zero-break)90│91├─ Angular (any major version)92│ ├─ Check: Run ng update for guided migration93│ ├─ Check: Review Angular Update Guide (update.angular.io)94│ ├─ Tool: ng update @angular/core @angular/cli95│ └─ Load: ./references/framework-upgrades.md96│97└─ Django (any major version)98 ├─ Check: Run python -Wd manage.py test for deprecation warnings99 ├─ Check: Review Django release notes for removals100 ├─ Tool: django-upgrade (automatic fixer)101 └─ Load: ./references/framework-upgrades.md102```103104## Dependency Audit Workflow105106```107Ecosystem?108│109├─ JavaScript / Node.js110│ ├─ npm audit / npm audit fix111│ ├─ npx audit-ci --moderate (CI integration)112│ └─ Socket.dev for supply chain analysis113│114├─ Python115│ ├─ pip-audit116│ ├─ safety check117│ └─ pip-audit --fix (auto-update vulnerable packages)118│119├─ Rust120│ ├─ cargo audit121│ └─ cargo deny check advisories122│123├─ Go124│ ├─ govulncheck ./...125│ └─ go list -m -u all (list available updates)126│127├─ PHP128│ ├─ composer audit129│ └─ composer outdated --direct130│131└─ Multi-ecosystem132 └─ Trivy, Snyk, or Dependabot across all133```134135## Pre-Migration Checklist136137```138[ ] Test coverage measured and documented (target: >70% for critical paths)139[ ] CI pipeline green on current version140[ ] All dependencies up to date (or pinned with rationale)141[ ] Database backup taken (if applicable)142[ ] Git state clean — migration branch created from latest main143[ ] Rollback plan documented and tested144[ ] Breaking change list reviewed from upstream changelog145[ ] Team notified of migration window146[ ] Feature flags in place for gradual rollout (if applicable)147[ ] Monitoring and alerting configured for regression detection148[ ] Performance baseline captured (response times, memory, CPU)149[ ] Lock file committed (package-lock.json, yarn.lock, Cargo.lock, etc.)150```151152## Breaking Change Detection Patterns153154```155How do you detect breaking changes?156│157├─ Semver Analysis158│ ├─ Major version bump → breaking changes guaranteed159│ ├─ Check CHANGELOG.md or BREAKING_CHANGES.md in repo160│ └─ npm: npx npm-check-updates --target major161│162├─ Changelog Parsing163│ ├─ Search for: "BREAKING", "removed", "deprecated", "renamed"164│ ├─ GitHub: compare releases page between versions165│ └─ Read migration guide if one exists166│167├─ Compiler / Runtime Warnings168│ ├─ Enable all deprecation warnings before upgrading169│ ├─ Python: python -Wd (turn deprecation warnings to errors)170│ ├─ Node: node --throw-deprecation171│ └─ TypeScript: strict mode catches type-level breaks172│173├─ Codemods (automated detection + fix)174│ ├─ jscodeshift — JavaScript/TypeScript AST transforms175│ ├─ ast-grep — language-agnostic structural search/replace176│ ├─ rector — PHP automated refactoring177│ ├─ gofmt / gofumpt — Go formatting changes178│ └─ 2to3 — Python 2 to 3 (legacy)179│180└─ Type Checking181 ├─ TypeScript: tsc --noEmit catches API shape changes182 ├─ Python: mypy / pyright after upgrade183 └─ Go: go vet ./... after upgrade184```185186## Codemod Quick Reference187188| Ecosystem | Tool | Command | Use Case |189|-----------|------|---------|----------|190| **JS/TS** | jscodeshift | `npx jscodeshift -t transform.ts src/` | Custom AST transforms |191| **JS/TS** | ast-grep | `sg --pattern 'old($$$)' --rewrite 'new($$$)'` | Structural find/replace |192| **React** | react-codemod | `npx codemod@latest react/19/migration-recipe` | React version upgrades |193| **Next.js** | next-codemod | `npx @next/codemod@latest` | Next.js version upgrades |194| **Vue** | vue-codemod | `npx @vue/codemod src/` | Vue 2 to 3 transforms |195| **PHP** | Rector | `vendor/bin/rector process src` | PHP version + framework upgrades |196| **Python** | pyupgrade | `pyupgrade --py314-plus *.py` | Python version syntax upgrades |197| **Python** | django-upgrade | `django-upgrade --target-version 5.0 *.py` | Django version upgrades |198| **Go** | gofmt | `gofmt -w .` | Go formatting updates |199| **Go** | gofix | `go fix ./...` | Go API changes |200| **Rust** | cargo fix | `cargo fix --edition` | Rust edition migration |201| **Multi** | ast-grep | `sg scan --rule rules.yml` | Any language with custom rules |202203## Rollback Strategy Decision Tree204205```206Migration failed or caused issues — how to roll back?207│208├─ Code-only change, no data migration209│ ├─ Small number of commits210│ │ └─ Git Revert211│ │ git revert --no-commit HEAD~N..HEAD && git commit212│ │ Pros: clean history, safe for shared branches213│ │ Cons: merge conflicts if code has diverged214│ │215│ └─ Entire feature branch216│ └─ Revert merge commit217│ git revert -m 1 <merge-commit-sha>218│219├─ Feature flag controlled220│ └─ Toggle flag off221│ Instant rollback, no deployment needed222│ Keep old code path until new path is proven223│224├─ Database schema changed225│ ├─ Reversible migration exists226│ │ └─ Run down migration227│ │ rails db:rollback / php artisan migrate:rollback / alembic downgrade228│ │229│ └─ Irreversible migration (dropped column, changed type)230│ └─ Restore from backup + replay write-ahead log231│ This is why you take backups BEFORE migration232│233└─ Infrastructure / deployment234 ├─ Blue-Green deployment235 │ └─ Switch traffic back to blue (old) environment236 │237 ├─ Canary deployment238 │ └─ Route 100% traffic back to stable version239 │240 └─ Container orchestration (K8s)241 └─ kubectl rollout undo deployment/app242```243244## Common Gotchas245246| Gotcha | Why It Happens | Prevention |247|--------|---------------|------------|248| Upgrading multiple major versions at once | Each major version may have sequential breaking changes that compound | Upgrade one major version at a time, verify, then proceed |249| Lock file not committed before migration | Cannot reproduce pre-migration dependency state | Always commit lock files; take a snapshot branch before starting |250| Running codemods without committing first | Cannot diff what the codemod changed vs your manual changes | Commit clean state, run codemod, commit codemod changes separately |251| Ignoring deprecation warnings in current version | Deprecated APIs are removed in next major version | Fix all deprecation warnings BEFORE upgrading |252| Testing only happy paths after migration | Edge cases and error paths are most likely to break | Run full test suite plus manual exploratory testing |253| Not checking transitive dependencies | A direct dep upgrade may pull in incompatible transitive deps | Use `npm ls`, `pip show`, `cargo tree` to inspect dependency tree |254| Assuming codemods catch everything | Codemods handle common patterns, not all patterns | Review codemod output manually; check for skipped files |255| Skipping the migration guide | Framework authors document known pitfalls and workarounds | Read the official migration guide end-to-end before starting |256| Migrating in a long-lived branch | Main branch diverges, causing painful merge conflicts | Use feature flags for incremental migration on main |257| Not updating CI to test both versions | CI passes on old version but new version has failures | Add matrix testing for both versions during transition |258| Database migration without backup | Irreversible schema changes with no recovery path | Always backup before migration; test rollback procedure |259| Forgetting to update Docker/CI base images | Code upgraded but runtime is still old version | Update Dockerfile FROM, CI config, and deployment manifests |260261## Reference Files262263| File | Contents | Lines |264|------|----------|-------|265| `references/framework-upgrades.md` | React 18→19, Next.js Pages→App Router, Vue 2→3, Laravel 10→13, Angular, Django upgrade paths | ~700 |266| `references/language-upgrades.md` | Python 3.9→3.14, Node 18→26, TypeScript 4→6, Go 1.20→1.26, Rust 2021→2024, PHP 8.1→8.5 | ~650 |267| `references/dependency-management.md` | Audit tools, update strategies, lock files, monorepo deps, supply chain security | ~550 |268269## Staleness verifier270271This skill hardcodes specific framework/language target versions (React 19, Laravel 13, Python 3.14, Node 26, TypeScript 6, Go 1.26, Rust 2024, PHP 8.5). [`scripts/check-migrate-facts.py`](scripts/check-migrate-facts.py) guards them against silent drift:272273```bash274# Structural (PR CI, no network): every catalogued target version still appears275# where it is recorded (description vs body), and the currency note carries a year.276python scripts/check-migrate-facts.py --offline # exit 0 consistent, 10 drift277278# Live (freshness job, never blocks a PR): each target is resolved against279# endoflife.date (python/nodejs/laravel/php/go) and npm (react/typescript).280python scripts/check-migrate-facts.py --live # exit 10 a target lags latest, 7 unreachable281```282283The canonical target-version list lives in [`assets/migrate-facts.json`](assets/migrate-facts.json); when you change a recommended target, update it to match or `--offline` fails CI. A `--live` drift means the skill is naming an older target than the ecosystem's current stable — review, don't auto-rewrite.284285## See Also286287| Skill | When to Combine |288|-------|----------------|289| `testing-ops` | Ensuring test coverage before migration, writing regression tests after |290| `debug-ops` | Diagnosing failures introduced by migration, bisecting breaking commits |291| `git-ops` | Branch strategy for migration, git bisect to find breaking change |292| `refactor-ops` | Code transformations that often accompany version upgrades |293| `ci-cd-ops` | Updating CI pipelines to test against new versions, matrix builds |294| `container-orchestration` | Updating base images, Dockerfile changes for new runtime versions |295| `security-ops` | Vulnerability remediation that triggers dependency upgrades |