Refactor / Cleanup Workflow
For Claude Code: Read this entire document when invoked via
/project:refactor. You are the enforcer of this workflow. Do not skip steps. Do not proceed to the next step until the current one is complete. Ask the developer for the required information at each gate — do not assume or infer it.
Purpose
A repeatable runbook for refactors, cleanups, and technical debt reduction in the jjk-workspace monorepo. The defining constraint of this workflow: no observable behavior changes. If it changes what a user sees or what a system does, it’s a feature, not a refactor.
This workflow exists because refactors are the highest-risk low-visibility work in a solo codebase. Easy to convince yourself you’re done. Easy to accidentally change behavior. Easy to skip the docs because “nothing changed.”
The Workflow
Step 1 — Define the Scope
Gate: What specifically is changing, and why?
Answer these before touching anything:
- What is the target? File(s), module(s), pattern(s), dependency(ies) — be specific.
- What is the problem being solved? Complexity, duplication, dead code, naming inconsistency, performance, bundle size — name it.
- What is explicitly out of scope? Name at least one thing you are not doing even if you’re tempted.
This is not a brief in the feature sense — it’s a scope boundary. The purpose is to prevent “while I’m in here” sprawl.
Claude Code: Ask the developer for scope, problem, and explicit out-of-scope. If the answer to #3 is “nothing” or vague, push back. Every refactor has a boundary.
Step 2 — Confirm: Refactor or Feature?
Gate: Does this change observable behavior?
If anything in the scope changes:
- What a user sees in the UI
- What an API or function returns
- What data is written to Firestore
- What events are emitted or logged
- What scheduled jobs do
…then it is not a refactor. Stop and switch to the Feature Workflow.
Pure refactors change structure, not behavior. Rename, restructure, extract, consolidate, simplify — all fine. Change what happens — feature.
Claude Code: Make this determination based on the scope. If there’s any ambiguity, ask the developer to describe what a user or system would notice differently after the change. If the answer is “nothing,” proceed. If anything, redirect to feature.
Step 3 — ADR Check
Does the refactor touch any ADR-governed decision?
Check the ADR log. If the refactor:
- Moves code across a boundary defined by an ADR
- Changes how shared libraries are consumed
- Alters a pattern that an ADR explicitly governs
…surface the conflict before proceeding. The ADR may need to be amended, or the refactor scope may need to shrink.
Claude Code: Check the ADR log against the defined scope. State clearly whether any ADRs are implicated.
Step 4 — Establish a Baseline
Gate: Tests pass before you touch anything.
Run the full test suite on the current state:
npm testIf tests fail before you start, stop. Fix those first (bug fix workflow) or document the pre-existing failures explicitly. Do not begin a refactor on a red baseline — you won’t know what you broke.
Claude Code: Run the test suite and confirm green baseline before proceeding. If red, report which tests are failing and ask the developer how to proceed.
Step 5 — Branch
Branch from main using the established convention:
refactor/<short-slug>Examples:
refactor/consolidate-linkedin-service
refactor/remove-dead-admin-routes
refactor/extract-firestore-query-helpers
refactor/rename-shared-model-interfaces
Claude Code: Confirm the branch name before creating it.
Step 6 — Refactor
Make the changes within the defined scope. Do not:
- Fix bugs you notice along the way (note them, fix them separately)
- Add new behavior opportunistically
- Expand scope beyond what was defined in Step 1
Work incrementally. Commit in logical units so the branch history is readable and bisectable if something breaks.
Step 7 — Verify No Behavior Change
Gate: Tests still pass. Nothing observable changed.
npm testTests must pass with the same results as the baseline. If new failures appear, the refactor changed behavior — find it and fix it before proceeding.
Additionally, do a manual spot-check of anything the test suite doesn’t cover: scheduled function behavior, Firebase rules, Terraform state if touched.
Claude Code: Run the test suite and compare to baseline. Do not proceed if any new failures appear. Identify the behavioral change and address it.
Step 8 — Docs Update (Conditional)
Most refactors don’t need new docs — the behavior didn’t change. But ask:
- Did the refactor change any pattern that the Project Spec describes? e.g., if you consolidated two services into one, update the spec to reflect the new structure.
- Did the refactor change anything the Claude Code Guide references? e.g., barrel paths, shared/ structure, naming conventions.
- Did the refactor amend an ADR-governed decision? Update the ADR if so.
If yes to any: update the doc in the same branch before merging. If no: proceed.
Claude Code: Ask these three questions. If any answer is yes, identify the specific doc and update it before closing the branch.
Step 9 — Commit
refactor: <plain description of what changed structurally>
Examples:
refactor: consolidate linkedin query logic into single service
refactor: remove unused admin route components and lazy chunks
refactor: extract shared Firestore helpers to @jjk/utils
Multiple commits on the branch are fine and encouraged for large refactors. Each commit should be independently coherent.
Step 10 — Deploy
Refactors still need to deploy. No behavior changed, but the running code did.
# Functions refactor
npx firebase deploy --only functions
# Frontend refactor
npx ng build frontend && npx firebase deploy --only hosting:blog
# Full
npm run build && firebase deploySpot-check in production. Confirm nothing that was working is now broken.
Quick Reference
| Step | Action | Gate |
|---|---|---|
| 1 | Define scope | Target, problem, explicit out-of-scope |
| 2 | Refactor or feature? | No observable behavior change confirmed |
| 3 | ADR check | No ADR-governed boundaries crossed |
| 4 | Baseline | Tests green before first change |
| 5 | Branch | refactor/<slug> created |
| 6 | Refactor | Within scope, incremental commits |
| 7 | Verify | Tests still green, no new failures |
| 8 | Docs | Updated only if spec, CC guide, or ADR affected |
| 9 | Commit | Conventional commits, readable history |
| 10 | Deploy | Live, spot-checked |