# Post Change Refactor

> Refactor and clean up the uncommitted change before committing. Eliminate duplication, rename unclear domain concepts, collapse shotgun surgery when another similar change is likely, remove dead / test-only / redundant code, split files larger than 250 lines into cohesive modules, and confirm related tests still pass. Use after finishing a phase or sub-phase and before commit, or whenever the developer asks to clean up the current change. Triggers on: refactor change, clean up change, post-change refactor, before commit cleanup, tidy current change.

- Skill: `terryyin/post-change-refactor` (Agent Skill)
- Install (CLI): `npx skillmds@latest add terryyin/post-change-refactor`
- Raw SKILL.md: https://api.skillmd.com/api/skills/terryyin/post-change-refactor/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: terryyin (https://skillmd.com/u/terryyin)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/terryyin/post-change-refactor

---


# Post-Change Refactor — Clean the Current Change Before Commit

## When to use

- After the implementation of a phase / sub-phase finishes and **before**
  the commit.
- On demand, when the developer asks to clean up or refactor the current
  uncommitted change.

Start with `.cursor/rules/` for project conventions and test practices.

## Scope: "the current change"

The current change = files touched since the last commit (staged + unstaged
+ untracked). Discover the scope:

```bash
git status
git diff
git diff --cached
```

**Git does not use the Nix prefix.** All other repo tooling does.

All refactoring work is scoped to those files and the files that
directly depend on them or are depended on by them. Do **not** sweep
unrelated parts of the repo.

## Decision boundary

Only keep code that is justified by **the current change** or by the
**immediate next phase** in the plan (if one exists).
Anything justified only by a phase further out, or by "we might need it
later", is speculative — remove it.

If there is no plan, justification must come entirely from the current
change.

## Procedure

Run each check below in order. After all checks pass, **hand control back
to the caller** — do **not** commit from inside this skill.

### 1. Duplication

- Look for **new** duplication introduced by the change (copy-pasted
  blocks, parallel structures with cosmetic differences).
- Look for duplication the change made **visible** — the new code repeats
  logic that already existed elsewhere.
- The same concept appearing in two representations counts as duplication,
  not just literal copies.
- **Action**: collapse onto a single representation. Prefer reusing an
  existing helper in the right layer (provider, `Translator`, CLI) over
  inventing a new one.

### 2. Domain naming

- Read every new or renamed identifier — files, modules, classes,
  functions, variables, tests, fixtures.
- Ask: does the name match what a domain reader expects? Does it match
  translate-python's language (providers, translation, CLI, languages,
  API keys, etc.)?
- **Action**: rename when intent is unclear, misleading, mixes layers, or
  leaks phase numbers / sequence info. Names describe **capability**, not
  development history.

### 3. Shotgun surgery

- A change is shotgun surgery when **one logical concept** forces edits
  in many places.
- Estimate the likelihood of another change of the same shape in the
  foreseeable future.
- **Action**:
  - **High likelihood** → consolidate the scattered edits behind a single
    seam (one function, one config, one module) so the next change touches
    one place. Do it now.
  - **Low likelihood** → leave it. Do not preemptively abstract.

### 4. Dead / redundant / cancelling code

Remove aggressively whatever the change introduced or exposed that is not
justified by the current change or the immediate next phase:

- Code with no caller.
- Branches that cannot be reached.
- Pairs of edits that cancel each other (added then immediately worked
  around, flag toggles that never flip, etc.).
- Production code only exercised by unit tests — no real caller from the
  CLI (`translate-cli`), `Translator` API, or provider pipeline.
- Unit tests that overlap with another test on the same observable
  surface (same input/output, same entry point).
- Tests that pin internal structure rather than observable behavior — if
  a test mainly mirrors the code's factoring, drop it in favor of the
  test that drives a high-level entry point (`translate-cli`, `Translator.translate`,
  CLI output).

When in doubt, **delete**. The next phase, if relevant, will reintroduce
only what it actually needs.

### 5. File size

For every file touched by the change, check line count:

```bash
wc -l <path>
```

- Files **over 250 lines** must be split. This rule is applied to test code as well.
- Split along **cohesive seams** — one concept per module, not arbitrary
  line cuts.
- Update imports. Keep the public API stable for callers outside the
  change.

### 6. Confirm related tests still pass

Run **related** tests for the changed files — not the whole suite. Use
`nix develop -c …` for all commands below except `git`.

| Area touched | Focused command |
|--------------|-----------------|
| Core translation (`translate/translate.py`) | `nix develop -c pytest tests/test_translate.py` |
| Provider (`translate/providers/`) | `nix develop -c pytest tests/test_provider.py` |
| CLI / options (`translate/main.py`, `translate/__main__.py`) | `nix develop -c pytest tests/test_main.py` |
| Broad or cross-cutting change | `nix develop -c pytest` |

Prefer CLI integration tests and VCR-backed translation tests over tests
that only exercise internal helpers.

All related tests must pass before returning. If a test breaks because of
the refactor (not the original change), fix it now.

## Return

Report a short summary to the caller:

1. Which checks led to changes — duplication / naming / shotgun /
   dead code / file size.
2. Files renamed, extracted, split, or deleted.
3. Which related tests were run and confirmed passing.

Then hand control back. **Do not commit from inside this skill** — the
caller commits.

## Out of scope

- Do not redesign code outside the changed files.
- Do not start a new phase or add new behavior. Only restructure and
  remove.
- Do not run the entire test suite or trigger CI from inside this skill
  unless the change is broad enough that focused tests cannot cover it.

