systematic-type-migration
Provides a structured workflow for safely migrating codebases from old types to new type-safe implementations using integration-test-first approach, file-by-file migration with incremental verification, and atomic commits to prevent integration bugs.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install cipherstash-cipherpowers-systematic-type-migration
Repository
Skill path: plugin/skills/systematic-type-migration
Provides a structured workflow for safely migrating codebases from old types to new type-safe implementations using integration-test-first approach, file-by-file migration with incremental verification, and atomic commits to prevent integration bugs.
Open repositoryBest for
Primary workflow: Ship Full Stack.
Technical facets: Full Stack, Testing, Integration.
Target audience: Rust developers undertaking major refactoring projects, especially those migrating to type-safe implementations or replacing components across large codebases.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: cipherstash.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install systematic-type-migration into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/cipherstash/cipherpowers before adding systematic-type-migration to shared team environments
- Use systematic-type-migration for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: Systematic Type Migration
description: Safe refactoring workflow for replacing old types with new type-safe implementations through integration-test-first, file-by-file migration with incremental verification
when_to_use: when refactoring to new type-safe implementations, replacing components across codebase, migrating to new domain types
version: 1.0.0
---
# Systematic Type Migration
## Overview
When refactoring components to new type-safe implementations, use this systematic workflow to prevent "works in isolation but broken integration" bugs.
**Core principle:** Integration test FIRST → file-by-file migration → incremental verification → cleanup
## The Problem
**Recurring issue during major refactoring:**
- Old component definitions remain in the codebase
- Some files spawn entities with old types
- Other files query for new types
- Systems become disconnected (queries find zero entities)
- User functionality breaks despite all systems being "properly registered"
**Example:** After introducing type-safe `MovementState` enum, if `setup.rs` spawns entities with the old `MovementState` but `planning.rs` queries for the new `MovementState`, queries will silently fail.
## The Workflow
### Phase 1: Preparation
**Step 1: Document the change**
- Create work directory (e.g., `docs/work/YYYY-MM-DD-type-safe-X`)
- Document scope and goals
**Step 2: Identify all uses**
```bash
# Find all references to the type being replaced
grep -r "ComponentName" src/
rg "OldType" --type rust
```
**Step 3: Create integration test FIRST**
- Write test that exercises **full user flow** (not just isolated system behavior)
- Test should verify end-to-end functionality
- This test MUST pass before starting AND after completion
**Step 4: Run baseline tests**
- Run project test command
- Run project check command
- Capture baseline to compare against
### Phase 2: Implementation
**Step 1: Create new component**
- Implement in canonical location (e.g., `src/components/movement/states.rs`)
- Include all required derives
**Step 2: Do NOT delete old component yet**
- Keep both during migration
- Enables gradual migration without breaking everything
- Allows atomic commits per file
### Phase 3: Migration (Systematic, File-by-File)
For EACH file using the old component:
**Step 1: Update imports**
```rust
// Before
use old_module::OldType;
// After
use new_module::NewType;
```
**Step 2: Update type usage**
- Pattern matching if enum variants changed
- Entity spawning to use new type
- Queries to use new type
**Step 3: Test after each file**
```bash
cargo check # Or language-specific quick check
```
- Catch type errors immediately
- Don't accumulate errors across files
**Step 4: Commit atomically**
```bash
git add path/to/file.rs
git commit -m "refactor: migrate FileX to new ComponentName"
```
- One commit per file or logical group
- Enables easy rollback if needed
**Common file locations to check:**
- Entity spawning files (e.g., `setup.rs`, `spawners.rs`)
- System logic files (business logic using the component)
- UI display files (rendering component state)
- Component definition files
- Integration test files
### Phase 4: Cleanup
**Step 1: Delete old component definition**
- Remove from original module
- Only after ALL references migrated
**Step 2: Remove obsolete imports**
```bash
# Find unused imports
cargo clippy -- -W unused_imports
```
**Step 3: Remove obsolete helper code**
- Builder functions
- Conversion utilities
- Deprecated APIs
**Step 4: Update exports**
- Remove old type from `mod.rs` public API
- Ensure new type properly exported
### Phase 5: Verification
**Step 1: Compile clean**
```bash
cargo check --all-targets
# Or language-specific equivalent
```
**Step 2: Run all tests**
Run project test command
- All unit tests must pass
- All integration tests must pass
**Step 3: Verify integration test passes**
- The test created in Phase 1 MUST pass
- This verifies end-to-end functionality
**Step 4: Run checks**
Run project check command
- Linting, formatting, type checking
**Step 5: Manual testing**
- Test actual user flows
- Verify UI updates correctly
- Check edge cases
### Phase 6: Documentation
**Step 1: Update pattern docs**
- If new pattern emerged, document it
**Step 2: Document in retrospective**
- Capture lessons learned in work directory
- Note any pitfalls encountered
**Step 3: Update project docs**
- If pattern is important, reference from CLAUDE.md or README
## Key Principles
| Principle | Rationale |
|-----------|-----------|
| **Integration test FIRST** | Prevents "works in parts, broken as whole" |
| **Keep both during migration** | Enables atomic commits per file |
| **File-by-file, not all-at-once** | Easier debugging, clear progress |
| **Incremental verification** | Catch errors immediately (5 min) vs batch (30+ min) |
| **Atomic commits** | Easy rollback if specific change breaks something |
## Prevention: Integration Tests
The best prevention is **integration tests that verify the full user flow**, not just isolated system behavior.
### What Makes a Good Integration Test
**Good integration test:**
```rust
#[test]
fn test_user_can_move_vehicle() {
// Setup: Spawn entities with realistic component combinations
let world = setup_test_world();
let vehicle = spawn_vehicle_with_all_components(&mut world);
// Act: Trigger user action (click → select → move)
click_vehicle(&mut world, vehicle);
issue_move_order(&mut world, target_position);
// Assert: Verify end result, not internal state
run_systems_until_complete(&mut world);
assert!(vehicle_arrived_at_target(&world, vehicle));
}
```
**Bad integration test:**
```rust
#[test]
fn test_planning_system_queries() {
// Only tests one system in isolation
// Doesn't verify components are actually compatible
}
```
**Integration test should:**
- Spawn entities with ALL required components (like real usage)
- Exercise multiple systems together (full pipeline)
- Verify user-visible outcome, not internal state
- Use realistic component combinations
## Common Mistakes
### Mistake 1: Skipping Integration Test
**Problem:** Discover breakage during manual testing (too late)
**Solution:** Write integration test FIRST, watch it pass LAST
### Mistake 2: Big-Bang Migration
**Problem:** Migrate all files at once, giant debug session when it fails
**Solution:** File-by-file with `cargo check` after each
### Mistake 3: Deleting Old Type Too Early
**Problem:** Can't compile during migration, hard to debug
**Solution:** Keep both until migration complete
### Mistake 4: Batching Commits
**Problem:** Hard to identify which change broke tests
**Solution:** Atomic commits per file
### Mistake 5: Testing Only Units
**Problem:** Units pass, integration broken (components incompatible)
**Solution:** Integration test MUST exercise full user flow
## Example Workflow
```bash
# Phase 1: Preparation
mkdir -p docs/work/2025-10-23-type-safe-movement-state
grep -r "MovementState" src/ > docs/work/2025-10-23-type-safe-movement-state/references.txt
# Write integration test: tests/movement_integration.rs
# Run project test command to establish baseline
# Phase 2: Implementation
# Create src/components/movement/states.rs with new MovementState
# Keep old src/space/components.rs::MovementState
# Phase 3: Migration (file-by-file)
# File 1: src/space/systems/setup.rs
nvim src/space/systems/setup.rs # Update import, spawning
cargo check # Verify
git add src/space/systems/setup.rs
git commit -m "refactor: migrate setup.rs to new MovementState"
# File 2: src/space/systems/planning.rs
nvim src/space/systems/planning.rs # Update import, queries
cargo check # Verify
git add src/space/systems/planning.rs
git commit -m "refactor: migrate planning.rs to new MovementState"
# ... repeat for each file ...
# Phase 4: Cleanup
# Delete old MovementState from src/space/components.rs
git add src/space/components.rs
git commit -m "refactor: remove old MovementState definition"
# Phase 5: Verification
cargo check --all-targets
# Run project test command - integration test MUST pass
# Run project check command
# Manual testing
# Phase 6: Documentation
# Write docs/work/2025-10-23-type-safe-movement-state/summary.md
```
## Related Practices
**Before using this skill:**
- Read: `${CLAUDE_PLUGIN_ROOT}principles/development.md` - Code structure principles
- Read: `${CLAUDE_PLUGIN_ROOT}principles/testing.md` - Testing principles
**After migration:**
- Use: `${CLAUDE_PLUGIN_ROOT}skills/requesting-code-review/SKILL.md` - Request code review
## Testing This Skill
See `test-scenarios.md` for pressure tests validating this workflow prevents integration breakage.