Refactoring Architect
Refactor existing code into maintainable modules without changing behavior.
Use tests as the safety rail: characterize first, extract, integrate, verify.
Absolute Rules
- Analyze before moving code. Understand behavior, deployment, tests, and public
contracts first.
- Write or identify focused tests before extraction. If no useful harness exists,
create the smallest one that protects the behavior being moved.
- Never change behavior during refactoring unless the user explicitly requested a
behavior fix. Keep signatures, errors, output, config, and deployment contracts
stable.
- Extract one cohesive module at a time by default. Multiple modules or multiple
repositories are allowed only when requested; still verify each change
independently.
- Do not mechanically split files by line count. Generated files, static content,
single-concern string constants, and standalone scripts deployed as one file may
be correct as-is.
- If the audit finds a repo already compliant, make only the specific fixes found;
do not invent refactors or infrastructure.
- If the user asks whether the project follows guidelines, asks you to finish a
previously narrow refactor, or challenges completeness, continue with a
concrete compliance audit and fixes. Do not merely answer that compliance is
unproven, and do not treat one small extraction as sufficient unless the audit
shows there are no other in-scope gaps.
- Never leave real dead code, unused imports, duplicate helpers, or orphaned
internal functions. Keep external compatibility surfaces until proven unused.
- Update documentation comments when moving public or non-obvious code.
- Always verify tests pass after each extraction step.
- Commit your finished work by default, in the worktree you are working on;
keep each extraction in its own commit.
- Do not refactor generated outputs, dependency folders, caches, vendored
packages, or build artifacts unless explicitly asked.
Step 1: Full Analysis
Prefer rg/rg --files and prune generated directories:
git status --short
rg --files -g '*.py' -g '*.sh' -g '*.js' -g '*.ts' -g '!**/.git/**' -g '!**/.venv/**' -g '!**/node_modules/**' -g '!**/__pycache__/**' -g '!**/build/**' -g '!**/dist/**' | xargs wc -l | sort -nr
rg -n '(^def |^class |^function |^[a-zA-Z_][a-zA-Z0-9_]*\(\))' -g '*.py' -g '*.sh' -g '*.js' -g '*.ts'
Identify:
- Monolith candidates: large files with multiple responsibilities, not merely
files over 200 lines.
- Cohesive groups that belong together by feature or boundary.
- Missing tests for behavior you will move or fix.
- Real dead code: unused imports, orphaned internals, obsolete tests, duplicate
helpers, and legacy paths proven unreachable.
- Compatibility surfaces: exported functions, CLI flags, aliases, wrappers,
generated entrypoints, and external contracts that must be kept or documented.
- Logging gaps on action paths, state transitions, boundary failures, external
calls, and meaningful decisions.
- Deployment risks: install copy lists, package data, service units, APT source
filenames, desktop entries, shell helper names, and required env/config.
For installed Python entrypoints, compare project-local imports against copied
helper modules or package manifests and add a regression test when gaps could
break clean installs.
- Static content where code rules should not be applied, such as prompt files,
generated data, string constants, docs, or vendored code.
- Misleading formatting or illogical code shape: stray indentation, duplicated
branches, dense expressions, silent broad exception swallowing, and tests
asserting obsolete paths.
For multi-repository workspaces:
- Inventory every repository first: git state, language/tooling, source count,
test count, largest source files, deployment path, and log sink.
- Do not mix unrelated repositories in one extraction. Finish and verify one
repo-level change before editing the next.
- Prioritize missing tests, behavior bugs, logging/deployment policy gaps, then
production monoliths with focused tests, then lower-risk cleanup.
- Run a second audit after edits using the same checks and compare against the
first pass.
Step 2: Plan the Structure
Write a numbered plan that names each extraction and its verification:
1. Extract database connection logic from app.py -> src/database/manager.py (with tests)
2. Extract auth parsing from app.py -> src/auth/parser.py (with tests)
3. Update imports and installer/package manifests
4. Run focused tests, then the relevant full suite
Each new module should have one responsibility, clear integration back to the
caller, public documentation where useful, existing or centralized logging, and
tests for public behavior.
Step 3: Test First
- For each function/class being extracted, create or identify tests before moving
it.
- If tests already exist, run the relevant subset before and after risky moves.
- Cover normal behavior, error paths, edge cases, and dependency interactions.
- For GNOME extensions, installers, CLI hooks, services, and environment-bound
code, extract pure helper logic first and test it locally. Keep platform calls
behind small wrappers that can be mocked.
- When adding shared dependencies such as a
log helper to sourced shell code,
update test stubs so isolated tests reflect the real dependency shape.
Use the repository's configured commands, for example:
pytest tests/test_<module_name>.py -v
bash tests/test_<module_name>.sh
npm test
Step 4: Extract One Module at a Time
For each extraction:
- Create the new file with concise header documentation when it introduces a
reusable module or script.
- Move the cohesive code.
- Update imports, call sites, install scripts, package manifests, copy lists,
and existence checks.
- Run focused tests.
- Read the diff for accidental behavior, output, logging, or deployment changes
before continuing.
Step 5: Logging During Refactors
When refactoring touches runtime code:
- Prefer the repository's existing centralized logger. Every project routes
logging through one centralized logging module; for Python projects, use
that module's standard call-tracing (
log_call) decorator instead of
inventing per-file helpers.
- Bash and shell scripts use one sourced logging helper from the project or
installer framework. During cleanup, remove old hardcoded log functions from
feature scripts, route call sites through the shared helper, and update
installer copy lists or package manifests whenever the helper must be present
in an installed copy.
- Repository-generated file logs belong under repo-root
.log/, and .log/
must be gitignored.
- Preserve stdout/stderr contracts for status bars, command substitution, CLI
filters, probes, TUIs, and installer-compatible formats.
- Use environment-appropriate sinks: journald/systemd or GNOME Shell logging for
services/extensions; stderr for installer contracts; file-only logging for
TUIs when terminal output would corrupt the interface.
- Logging coverage means action paths, state changes, external calls, boundary
failures, and meaningful decisions are observable. Pure helpers, parsers,
formatters, recursive generators, hot loops, logging primitives, and generated
shims may be covered by caller-level logs.
- Avoid high-frequency log spam. Log summaries and decisions around hot paths.
- Logging in hooks and installers must be best-effort and never abort the user
workflow.
- API logging must capture lifecycle/failures without secrets or sensitive
payloads.
Step 6: Verify
Run focused tests first, then the relevant full suite when practical:
pytest tests/ -v --tb=short
ruff check .
npm run lint
npm run typecheck
rg -n '(^def |^class |^function |^[a-zA-Z_][a-zA-Z0-9_]*\(\))' -g '*.py' -g '*.sh' -g '*.js' -g '*.ts' -g '!**/__pycache__/**'
Run configured lint/type checks only if the repository already provides them.
Do not install new lint tools ad hoc to satisfy this step. For Python dependency
changes or new Python projects, follow the init-project skill and the
supply-chain policy instead of direct pip install.
Also verify:
- No broken imports or missing deployed modules remain.
- No real dead code, unused imports, duplicate helpers, or obsolete tests remain.
- Required config is validated before side effects.
- Output formats and externally documented behavior are unchanged.
- Installer and service changes still work in the repo's tested root/non-root or
user/system modes.
- For broad compliance work, explicitly say which checks were run and which
residual risks remain; avoid claiming certainty beyond the evidence.
Step 7: Update Documentation
Update README/docs only when refactoring changes module layout, install behavior,
commands, logging, architecture, or usage. Keep docs proportional: project tree,
module responsibilities, import examples, and test commands are useful when they
help future maintainers.
Example: Refactoring a Monolithic install.sh
- Analyze: source count, function list, git state, tests, manifests, log sink.
- Identify feature groups: packages, GNOME extensions, services, keybindings.
- Plan
lib/packages.sh, lib/gnome_extensions.sh, lib/services.sh, etc.
- Write or run focused tests for the first group.
- Extract one group, update
install.sh and copy/check lists, then verify.
- Repeat for the next group.
- Run a second audit and relevant installer tests in a temporary home or
sandbox when available.
1---2name: refactoring3description: Use when the user asks to refactor, restructure, or modularize an existing codebase. Extracts monolithic files into well-organized modules following single-responsibility principles, audits multi-repository workspaces, creates tests first (TDD), and ensures extracted code is documented, logged, and verified. Always analyze and plan module boundaries before touching code.4---56# Refactoring Architect78Refactor existing code into maintainable modules without changing behavior.9Use tests as the safety rail: characterize first, extract, integrate, verify.1011## Absolute Rules1213- Analyze before moving code. Understand behavior, deployment, tests, and public14 contracts first.15- Write or identify focused tests before extraction. If no useful harness exists,16 create the smallest one that protects the behavior being moved.17- Never change behavior during refactoring unless the user explicitly requested a18 behavior fix. Keep signatures, errors, output, config, and deployment contracts19 stable.20- Extract one cohesive module at a time by default. Multiple modules or multiple21 repositories are allowed only when requested; still verify each change22 independently.23- Do not mechanically split files by line count. Generated files, static content,24 single-concern string constants, and standalone scripts deployed as one file may25 be correct as-is.26- If the audit finds a repo already compliant, make only the specific fixes found;27 do not invent refactors or infrastructure.28- If the user asks whether the project follows guidelines, asks you to finish a29 previously narrow refactor, or challenges completeness, continue with a30 concrete compliance audit and fixes. Do not merely answer that compliance is31 unproven, and do not treat one small extraction as sufficient unless the audit32 shows there are no other in-scope gaps.33- Never leave real dead code, unused imports, duplicate helpers, or orphaned34 internal functions. Keep external compatibility surfaces until proven unused.35- Update documentation comments when moving public or non-obvious code.36- Always verify tests pass after each extraction step.37- Commit your finished work by default, in the worktree you are working on;38 keep each extraction in its own commit.39- Do not refactor generated outputs, dependency folders, caches, vendored40 packages, or build artifacts unless explicitly asked.4142## Step 1: Full Analysis4344Prefer `rg`/`rg --files` and prune generated directories:4546```bash47git status --short48rg --files -g '*.py' -g '*.sh' -g '*.js' -g '*.ts' -g '!**/.git/**' -g '!**/.venv/**' -g '!**/node_modules/**' -g '!**/__pycache__/**' -g '!**/build/**' -g '!**/dist/**' | xargs wc -l | sort -nr49rg -n '(^def |^class |^function |^[a-zA-Z_][a-zA-Z0-9_]*\(\))' -g '*.py' -g '*.sh' -g '*.js' -g '*.ts'50```5152Identify:531. Monolith candidates: large files with multiple responsibilities, not merely54 files over 200 lines.552. Cohesive groups that belong together by feature or boundary.563. Missing tests for behavior you will move or fix.574. Real dead code: unused imports, orphaned internals, obsolete tests, duplicate58 helpers, and legacy paths proven unreachable.595. Compatibility surfaces: exported functions, CLI flags, aliases, wrappers,60 generated entrypoints, and external contracts that must be kept or documented.616. Logging gaps on action paths, state transitions, boundary failures, external62 calls, and meaningful decisions.637. Deployment risks: install copy lists, package data, service units, APT source64 filenames, desktop entries, shell helper names, and required env/config.65 For installed Python entrypoints, compare project-local imports against copied66 helper modules or package manifests and add a regression test when gaps could67 break clean installs.688. Static content where code rules should not be applied, such as prompt files,69 generated data, string constants, docs, or vendored code.709. Misleading formatting or illogical code shape: stray indentation, duplicated71 branches, dense expressions, silent broad exception swallowing, and tests72 asserting obsolete paths.7374For multi-repository workspaces:751. Inventory every repository first: git state, language/tooling, source count,76 test count, largest source files, deployment path, and log sink.772. Do not mix unrelated repositories in one extraction. Finish and verify one78 repo-level change before editing the next.793. Prioritize missing tests, behavior bugs, logging/deployment policy gaps, then80 production monoliths with focused tests, then lower-risk cleanup.814. Run a second audit after edits using the same checks and compare against the82 first pass.8384## Step 2: Plan the Structure8586Write a numbered plan that names each extraction and its verification:8788```text891. Extract database connection logic from app.py -> src/database/manager.py (with tests)902. Extract auth parsing from app.py -> src/auth/parser.py (with tests)913. Update imports and installer/package manifests924. Run focused tests, then the relevant full suite93```9495Each new module should have one responsibility, clear integration back to the96caller, public documentation where useful, existing or centralized logging, and97tests for public behavior.9899## Step 3: Test First100101- For each function/class being extracted, create or identify tests before moving102 it.103- If tests already exist, run the relevant subset before and after risky moves.104- Cover normal behavior, error paths, edge cases, and dependency interactions.105- For GNOME extensions, installers, CLI hooks, services, and environment-bound106 code, extract pure helper logic first and test it locally. Keep platform calls107 behind small wrappers that can be mocked.108- When adding shared dependencies such as a `log` helper to sourced shell code,109 update test stubs so isolated tests reflect the real dependency shape.110111Use the repository's configured commands, for example:112113```bash114pytest tests/test_<module_name>.py -v115bash tests/test_<module_name>.sh116npm test117```118119## Step 4: Extract One Module at a Time120121For each extraction:1221. Create the new file with concise header documentation when it introduces a123 reusable module or script.1242. Move the cohesive code.1253. Update imports, call sites, install scripts, package manifests, copy lists,126 and existence checks.1274. Run focused tests.1285. Read the diff for accidental behavior, output, logging, or deployment changes129 before continuing.130131## Step 5: Logging During Refactors132133When refactoring touches runtime code:1341. Prefer the repository's existing centralized logger. Every project routes135 logging through one centralized logging module; for Python projects, use136 that module's standard call-tracing (`log_call`) decorator instead of137 inventing per-file helpers.1382. Bash and shell scripts use one sourced logging helper from the project or139 installer framework. During cleanup, remove old hardcoded log functions from140 feature scripts, route call sites through the shared helper, and update141 installer copy lists or package manifests whenever the helper must be present142 in an installed copy.1433. Repository-generated file logs belong under repo-root `.log/`, and `.log/`144 must be gitignored.1454. Preserve stdout/stderr contracts for status bars, command substitution, CLI146 filters, probes, TUIs, and installer-compatible formats.1475. Use environment-appropriate sinks: journald/systemd or GNOME Shell logging for148 services/extensions; stderr for installer contracts; file-only logging for149 TUIs when terminal output would corrupt the interface.1506. Logging coverage means action paths, state changes, external calls, boundary151 failures, and meaningful decisions are observable. Pure helpers, parsers,152 formatters, recursive generators, hot loops, logging primitives, and generated153 shims may be covered by caller-level logs.1547. Avoid high-frequency log spam. Log summaries and decisions around hot paths.1558. Logging in hooks and installers must be best-effort and never abort the user156 workflow.1579. API logging must capture lifecycle/failures without secrets or sensitive158 payloads.159160## Step 6: Verify161162Run focused tests first, then the relevant full suite when practical:163164```bash165pytest tests/ -v --tb=short166ruff check .167npm run lint168npm run typecheck169rg -n '(^def |^class |^function |^[a-zA-Z_][a-zA-Z0-9_]*\(\))' -g '*.py' -g '*.sh' -g '*.js' -g '*.ts' -g '!**/__pycache__/**'170```171172Run configured lint/type checks only if the repository already provides them.173Do not install new lint tools ad hoc to satisfy this step. For Python dependency174changes or new Python projects, follow the `init-project` skill and the175supply-chain policy instead of direct `pip install`.176177Also verify:178- No broken imports or missing deployed modules remain.179- No real dead code, unused imports, duplicate helpers, or obsolete tests remain.180- Required config is validated before side effects.181- Output formats and externally documented behavior are unchanged.182- Installer and service changes still work in the repo's tested root/non-root or183 user/system modes.184- For broad compliance work, explicitly say which checks were run and which185 residual risks remain; avoid claiming certainty beyond the evidence.186187## Step 7: Update Documentation188189Update README/docs only when refactoring changes module layout, install behavior,190commands, logging, architecture, or usage. Keep docs proportional: project tree,191module responsibilities, import examples, and test commands are useful when they192help future maintainers.193194## Example: Refactoring a Monolithic `install.sh`1951961. Analyze: source count, function list, git state, tests, manifests, log sink.1972. Identify feature groups: packages, GNOME extensions, services, keybindings.1983. Plan `lib/packages.sh`, `lib/gnome_extensions.sh`, `lib/services.sh`, etc.1994. Write or run focused tests for the first group.2005. Extract one group, update `install.sh` and copy/check lists, then verify.2016. Repeat for the next group.2027. Run a second audit and relevant installer tests in a temporary home or203 sandbox when available.