skills/refactor/SKILL.md
Clean up implementation code while keeping tests green. Improve code quality without changing behaviour. Use after implement phase to polish code before review.
npx skillsauth add sofer/.agents refactorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Improve code structure and quality while keeping all tests passing. This completes the TDD red-green-refactor cycle.
Refactoring improves code without changing behaviour:
Expect from orchestrator:
Tests must stay green throughout refactoring.
After every change, run tests. If tests fail, the change altered behaviour - revert and try a different approach.
Verify all tests pass before starting:
npm test
# ✓ All tests passing
Review code for:
Code smells:
Standards alignment:
// Before
async createUser(input: CreateUserInput): Promise<User> {
const email = input.email.toLowerCase().trim();
if (!email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) {
throw new ValidationError('Invalid email');
}
// ... more code
}
// After
async createUser(input: CreateUserInput): Promise<User> {
const email = this.normaliseEmail(input.email);
this.validateEmail(email);
// ... more code
}
private normaliseEmail(email: string): string {
return email.toLowerCase().trim();
}
private validateEmail(email: string): void {
if (!email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) {
throw new ValidationError('Invalid email');
}
}
// Before
if (name.length > 100) { ... }
// After
const MAX_NAME_LENGTH = 100;
if (name.length > MAX_NAME_LENGTH) { ... }
// Before
const d = new Date();
const u = await repo.save(data);
// After
const createdAt = new Date();
const savedUser = await userRepository.save(userData);
// Before
if (user !== null && user !== undefined) {
if (user.active === true) {
return user;
}
}
return null;
// After
if (user?.active) {
return user;
}
return null;
// Before (in multiple methods)
const email = input.email.toLowerCase().trim();
// After (extracted to shared method)
const email = this.normaliseEmail(input.email);
// Before
function createUser(email: string, name: string, role: string, department: string)
// After
function createUser(input: CreateUserInput)
# Watch mode for instant feedback
npm test -- --watch
After all refactoring:
refactor:
story_id: "US-001"
changes:
- type: "extract_method"
description: "Extracted email normalisation to separate method"
files: ["src/services/user.service.ts"]
rationale: "Reused in multiple places, improves readability"
- type: "rename"
description: "Renamed 'u' to 'savedUser' for clarity"
files: ["src/services/user.service.ts"]
rationale: "Improves code readability"
- type: "extract_constant"
description: "Extracted MAX_EMAIL_LENGTH constant"
files: ["src/services/user.service.ts", "src/types/constants.ts"]
rationale: "Removes magic number, centralises configuration"
- type: "simplify"
description: "Simplified null check using optional chaining"
files: ["src/repositories/user.repository.ts"]
rationale: "Modern syntax, more readable"
run_result:
command: "npm test"
total: 12
passed: 12
failed: 0
status: "green" # Required - unchanged from implement
decisions:
- decision: "Kept validation in service layer"
rationale: "Consistent with existing pattern; controller stays thin"
notes: "Minor refactoring only; implementation was already clean"
Update manifest:
stories:
US-001:
phase: "refactor"
decisions:
- phase: "refactor"
decision: "Extracted email normalisation"
rationale: "DRY principle, used in 3 places"
Must pass before proceeding to code-review:
tools
Check whether Claude and Codex have equivalent access to shared agent resources, skills, hooks, plugins, MCP servers, permissions, startup behaviour, and provider-specific adapter config. Use when comparing agent environments, debugging missing capabilities after restart, or deciding whether to symlink a resource or configure a runtime.
testing
Record substantive skill use in an append-only local log. Use after choosing or invoking a non-system skill for real work, when a skill is inspected but not used, or when a skill fails to apply. Do not use for routine system skills or incidental file reads.
testing
Turn a vague or underspecified request into a self-contained problem statement. Use when the user has a rough idea, when a request would fail if handed directly to an agent, or before non-trivial work that needs shared understanding.
data-ai
Append a one-line learning to ~/.agents/learning-log.md. Use when the user types /learning, or when something genuinely worth remembering surfaced during work and the user confirms it should be captured.