refactor
refactorextractmovesplitrenamerestructurecode-quality
/install automation refactor Run in a Soma session to add to your project.
curl -sO https://raw.githubusercontent.com/meetsoma/community/main/automations/refactor.md Download and copy to .soma/automations/refactor.md — or view on GitHub ↗
Details
Refactor
TL;DR
Scan blast radius → map functions → graph dependencies → plan changes → execute one concern per commit → keep backward compat during transition → run tests after every file change. Before deleting anything, search for references. Export from both old and new locations temporarily. Delete old only after full verification.
Extract, move, or restructure code safely. Follows an incremental pattern — scan first, plan the blast radius, execute one concern at a time, verify after every change.
Pre-Flight (before touching code)
- Scan blast radius — grep for the target name across the entire project. Who imports it? Who calls it? Who tests it?
- Map functions — understand the file's structure before editing. Know what functions exist and where they start.
- Graph dependencies — what does this file import? What imports it? Draw the dependency chain.
- Find duplicates — are there patterns to merge during this refactor?
Execute
- One concern per commit — types first, then implementations, then callers, then tests.
- Keep backward compatibility during transition — export from both old and new locations temporarily.
- Run tests after every file change, not just at the end.
Deleting Code
Deleting is a special case of refactoring. Before deleting any file:
- Search for the filename across the project — who references it?
- Check scripts that
sourceor call it - Check CI workflows (
.github/workflows/) - Check documentation that references it by name
Lesson: Deleting a "dead file" broke a ship pipeline because another script called it. The search would have caught it — but it felt safe to skip because "it's just deleting a dead file." Deleting is never just deleting.
Renaming Fields
When renaming a field (config key, frontmatter field, API parameter):
- Update the parser to handle BOTH old and new (backwards compat)
- Update all tests that assert on the old field name
- Update validation scripts that check for the old field
- Update documentation
- Create a migration if users have data with the old format
Lesson: Renamed a field in the parser but forgot to update 4 other files that referenced the old name. Each one was a separate discovery. The checklist above is the complete list from that incident.
Verify
- [ ] Tests pass — all suites, not just the changed one
- [ ] Build passes — compile/typecheck catches what tests miss
- [ ] No orphaned references — grep for old names, paths, imports
- [ ] Docs updated — reference new location/name
- [ ] Committed and pushed
Anti-Patterns
| Trap | Do This Instead |
|---|---|
| Moving code + changing logic in one commit | Separate: move first, change logic second |
| Deleting without searching for references | Always search the full project first |
| Renaming in code but not in tests/docs | One commit wave: code + tests + docs |
| Refactoring while debugging | Fix the bug first. Refactor next session. |
| Trusting memory about what references a file | Search. Memory is wrong more often than right. |