一键导入
refactoring-safely
Use when refactoring code - test-preserving transformations in small steps, running tests between each change
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when refactoring code - test-preserving transformations in small steps, running tests between each change
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use to audit test quality with Google Fellow SRE scrutiny - identifies tautological tests, coverage gaming, weak assertions, missing corner cases. Creates bd epic with tasks for improvements, then runs SRE task refinement on each.
Use when creating or developing anything, before writing code - refines rough ideas into bd epics with immutable requirements
Use when creating Claude Code hooks - covers hook patterns, composition, testing, progressive enhancement from simple to advanced
Use when encountering bugs or test failures - systematic debugging using debuggers, internet research, and agents to find root cause before fixing
Use when facing 3+ independent failures that can be investigated without shared state or dependencies - dispatches multiple agents to investigate and fix independent problems concurrently
Execute entire bd epic autonomously via subagent-per-task dispatch loop. Setup, dispatch subagent per task, end-of-epic review, branch completion.
| name | refactoring-safely |
| description | Use when refactoring code - test-preserving transformations in small steps, running tests between each change |
<kimi_compat> This skill was ported to Kimi Code CLI. In Kimi:
/skill:name or let the model invoke them automatically.SetTodoList tool.Agent tool.Agent calls with run_in_background=true.<rigidity_level> MEDIUM FREEDOM - Follow the change→test→commit cycle strictly, but adapt the specific refactoring patterns to your language and codebase. </rigidity_level>
<quick_reference>
| Step | Action | Verify |
|---|---|---|
| 1 | Run full test suite | ALL pass |
| 2 | Create bd refactoring task | Track work |
| 3 | Make ONE small change | Compiles |
| 4 | Run tests immediately | ALL still pass |
| 5 | Commit with descriptive message | History clear |
| 6 | Repeat 3-5 until complete | Each step safe |
| 7 | Final verification & close bd | Done |
Core cycle: Change → Test → Commit (repeat until complete) </quick_reference>
<when_to_use>
Don't use for:
<the_process>
BEFORE any refactoring:
# Use test-runner agent to keep context clean
Dispatch /skill:test-runner agent: "Run: cargo test"
Verify: ALL tests pass. If any fail, fix them FIRST, then refactor.
Why: Failing tests mean you can't detect if refactoring breaks things.
Track the refactoring work:
tm create "Refactor: Extract user validation logic" \
--type task \
--priority P2
tm update bd-456 --design "
## Goal
Extract user validation logic from UserService into separate Validator class.
## Why
- Validation duplicated across 3 services
- Makes testing individual validations difficult
- Violates single responsibility
## Approach
1. Create UserValidator class
2. Extract email validation
3. Extract name validation
4. Extract age validation
5. Update UserService to use validator
6. Remove duplication from other services
## Success Criteria
- All existing tests still pass
- No behavior changes
- Validator has 100% test coverage
"
tm update bd-456 --status in_progress
The smallest transformation that compiles.
Examples of "small":
NOT small:
Example:
// Before
fn create_user(name: &str, email: &str) -> Result<User> {
if email.is_empty() {
return Err(Error::InvalidEmail);
}
if !email.contains('@') {
return Err(Error::InvalidEmail);
}
let user = User { name, email };
Ok(user)
}
// After - ONE small change (extract email validation)
fn create_user(name: &str, email: &str) -> Result<User> {
validate_email(email)?;
let user = User { name, email };
Ok(user)
}
fn validate_email(email: &str) -> Result<()> {
if email.is_empty() {
return Err(Error::InvalidEmail);
}
if !email.contains('@') {
return Err(Error::InvalidEmail);
}
Ok(())
}
After EVERY small change:
Dispatch /skill:test-runner agent: "Run: cargo test"
Verify: ALL tests still pass.
If tests fail:
git restore src/file.rsNever proceed with failing tests.
Commit each safe transformation:
Dispatch /skill:test-runner agent: "Run: git add src/user_service.rs && git commit -m 'refactor(bd-456): extract email validation to function
No behavior change. All tests pass.
Part of bd-456'"
Why commit so often:
Repeat steps 3-5 for each small transformation:
1. Extract validate_email() ✓ (committed)
2. Extract validate_name() ✓ (committed)
3. Extract validate_age() ✓ (committed)
4. Create UserValidator struct ✓ (committed)
5. Move validations into UserValidator ✓ (committed)
6. Update UserService to use validator ✓ (committed)
7. Remove validation from OrderService ✓ (committed)
8. Remove validation from AccountService ✓ (committed)
Pattern: change → test → commit (repeat)
After all transformations complete:
# Full test suite
Dispatch /skill:test-runner agent: "Run: cargo test"
# Linter
Dispatch /skill:test-runner agent: "Run: cargo clippy"
Review the changes:
# See all refactoring commits
git log --oneline | grep "bd-456"
# Review full diff
git diff main...HEAD
Checklist:
Close bd task:
tm update bd-456 --design "
... (append to existing design)
## Completed
- Created UserValidator class with email, name, age validation
- Removed duplicated validation from 3 services
- All tests pass (verified)
- No behavior changes
- 8 small transformations, each tested
"
tm close bd-456
</the_process>
Developer changes behavior while "refactoring"
// Original code
fn validate_email(email: &str) -> Result<()> {
if email.is_empty() {
return Err(Error::InvalidEmail);
}
if !email.contains('@') {
return Err(Error::InvalidEmail);
}
Ok(())
}
// "Refactored" version
fn validate_email(email: &str) -> Result<()> {
if email.is_empty() {
return Err(Error::InvalidEmail);
}
if !email.contains('@') {
return Err(Error::InvalidEmail);
}
// NEW: Added extra validation
if !email.contains('.') { // BEHAVIOR CHANGE
return Err(Error::InvalidEmail);
}
Ok(())
}
<why_it_fails>
What you gain:
# Changes made all at once:
- Renamed 15 functions across 5 files
- Extracted 3 new classes
- Moved code between 10 files
- Reorganized module structure
- Updated all import statements
Then runs tests
$ cargo test
... 23 test failures ...
Now what? Which change broke what?
<why_it_fails>
If test fails:
What you gain:
// Legacy code with no tests
fn process_payment(amount: f64, user_id: i64) -> Result {
// 200 lines of complex payment logic
// Multiple edge cases
// No tests exist
}
// Developer refactors without tests:
// - Extracts 5 methods
// - Renames variables
// - Simplifies conditionals
// - "Looks good to me!"
// Deploys to production
// 💥 Payments fail for amounts over $1000
// Edge case handling was accidentally changed
<why_it_fails>
Write tests FIRST (using /skill:test-driven-development)
Then refactor with tests as safety net
Tests catch any behavior changes immediately
What you gain:
<refactor_vs_rewrite>
Rule: If you need to change test assertions (not just add tests), you're rewriting, not refactoring.
When to use:
How it works:
Example:
Legacy: Monolithic user service (50K LOC)
Goal: Microservices architecture
Step 1 (Transform):
- Create new UserService microservice
- Implement user creation endpoint
- Tests pass in isolation
Step 2 (Coexist):
- Add routing layer (façade)
- Route POST /users to new service
- Route GET /users to legacy service (for now)
- Monitor both, compare results
Step 3 (Eliminate):
- Once confident, migrate GET /users to new service
- Remove user creation from legacy
- Repeat for remaining endpoints
Benefits:
Use refactoring within components, Strangler Fig for replacing systems. </refactor_vs_rewrite>
<critical_rules>
All of these mean: Stop and return to the change→test→commit cycle
<verification_checklist> Before marking refactoring complete:
Can't check all boxes? Return to process and fix before closing bd task. </verification_checklist>
**This skill requires:** - /skill:test-driven-development (for writing tests before refactoring if none exist) - /skill:verification-before-completion (for final verification) - /skill:test-runner agent (for running tests without context pollution)This skill is called by:
Agents used:
When stuck: