Systematic Type Migration
Safe refactoring workflow for replacing old types with new type-safe implementations through integration-test-first, file-by-file migration with incremental verification
What this skill does
# 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/develoRelated in Code Review
gstack
IncludedFast headless browser for QA testing and site dogfooding. Navigate pages, interact with elements, verify state, diff before/after, take annotated screenshots, test responsive layouts, forms, uploads, dialogs, and capture bug evidence. Use when asked to open or test a site, verify a deployment, dogfood a user flow, or file a bug with screenshots. (gstack)
startup-due-diligence
IncludedLegal due diligence review for seed-stage and Series A startups (US, Delaware C-Corp focus). Supports both investor and founder perspectives. Capabilities include: (1) Interactive document review and issue spotting; (2) Document request list generation; (3) Cap table and SAFE/convertible note analysis; (4) Red flag identification with severity ratings; (5) Diligence report generation. TRIGGERS: due diligence, DD, startup investment, cap table review, Series A, seed round, investor diligence, legal review startup, SAFE analysis, convertible note, 409A, founder vesting.
interview-master
IncludedThis skill should be used when the user asks to "generate interview questions", "prepare for interview", "optimize resume", "conduct mock interview", "analyze git commits for resume", "generate resume from code", "review my resume", or mentions interview preparation, career assistance, or extracting project experience from git history. Provides comprehensive interview and career development guidance for both job seekers and interviewers.
fix-issue
IncludedFixes GitHub issues using parallel analysis agents for root cause investigation, code exploration, and regression detection. Reads issue context from gh CLI, searches codebase and memory for related patterns, generates a fix with tests, and links the resolution back to the issue via PR. Includes prevention analysis to avoid recurrence. Use when debugging errors, resolving regressions, fixing bugs, or triaging issues.
sf-apex
IncludedGenerates and reviews Salesforce Apex code with 150-point scoring. TRIGGER when: user writes, reviews, or fixes Apex classes, triggers, test classes, batch/queueable/schedulable jobs, or touches .cls/.trigger files. DO NOT TRIGGER when: LWC JavaScript (use sf-lwc), Flow XML (use sf-flow), SOQL-only queries (use sf-soql), or non-Salesforce code.
swift-development
IncludedComprehensive Swift development for building, testing, and deploying iOS/macOS applications. Use when Claude needs to: (1) Build Swift packages or Xcode projects from command line, (2) Run tests with XCTest or Swift Testing framework, (3) Manage iOS simulators with simctl, (4) Handle code signing, provisioning profiles, and app distribution, (5) Format or lint Swift code with SwiftFormat/SwiftLint, (6) Work with Swift Package Manager (SPM), (7) Implement Swift 6 concurrency patterns (async/await, actors, Sendable), (8) Create SwiftUI views with MVVM architecture, (9) Set up Core Data or SwiftData persistence, or any other Swift/iOS/macOS development tasks.