Safe refactoring workflow for replacing old types with new type-safe implementations through integration-test-first, file-by-file migration with incremental verification
Systematic type migration workflow that prevents integration breakage during refactoring. Use when replacing old types with new type-safe implementations. Triggers on major refactoring tasks requiring component/type changes across multiple files.
/plugin marketplace add cipherstash/cipherpowers/plugin install cipherpowers@cipherpowersThis skill inherits all available tools. When active, it can use any tool Claude has access to.
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
Recurring issue during major refactoring:
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.
Step 1: Document the change
docs/work/YYYY-MM-DD-type-safe-X)Step 2: Identify all uses
# Find all references to the type being replaced
grep -r "ComponentName" src/
rg "OldType" --type rust
Step 3: Create integration test FIRST
Step 4: Run baseline tests
Step 1: Create new component
src/components/movement/states.rs)Step 2: Do NOT delete old component yet
For EACH file using the old component:
Step 1: Update imports
// Before
use old_module::OldType;
// After
use new_module::NewType;
Step 2: Update type usage
Step 3: Test after each file
cargo check # Or language-specific quick check
Step 4: Commit atomically
git add path/to/file.rs
git commit -m "refactor: migrate FileX to new ComponentName"
Common file locations to check:
setup.rs, spawners.rs)Step 1: Delete old component definition
Step 2: Remove obsolete imports
# Find unused imports
cargo clippy -- -W unused_imports
Step 3: Remove obsolete helper code
Step 4: Update exports
mod.rs public APIStep 1: Compile clean
cargo check --all-targets
# Or language-specific equivalent
Step 2: Run all tests
Run project test command
Step 3: Verify integration test passes
Step 4: Run checks
Run project check command
Step 5: Manual testing
Step 1: Update pattern docs
Step 2: Document in retrospective
Step 3: Update project docs
| 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 |
The best prevention is integration tests that verify the full user flow, not just isolated system behavior.
Good integration test:
#[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:
#[test]
fn test_planning_system_queries() {
// Only tests one system in isolation
// Doesn't verify components are actually compatible
}
Integration test should:
Problem: Discover breakage during manual testing (too late) Solution: Write integration test FIRST, watch it pass LAST
Problem: Migrate all files at once, giant debug session when it fails
Solution: File-by-file with cargo check after each
Problem: Can't compile during migration, hard to debug Solution: Keep both until migration complete
Problem: Hard to identify which change broke tests Solution: Atomic commits per file
Problem: Units pass, integration broken (components incompatible) Solution: Integration test MUST exercise full user flow
# 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
Before using this skill:
${CLAUDE_PLUGIN_ROOT}principles/development.md - Code structure principles${CLAUDE_PLUGIN_ROOT}principles/testing.md - Testing principlesAfter migration:
${CLAUDE_PLUGIN_ROOT}skills/requesting-code-review/SKILL.md - Request code reviewSee test-scenarios.md for pressure tests validating this workflow prevents integration breakage.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.