Clean up the following code in [LANGUAGE AND VERSION]. The code and surrounding context are [CODE AND CONTEXT]. Its current behavior, callers, and acceptance criteria are [CURRENT BEHAVIOR]. These are the constraints: [CONSTRAINTS AND STYLE]. Relevant tests, errors, or known edge cases are [TESTS AND EDGE CASES]. Treat this as a behavior-preserving refactor unless I explicitly authorize a behavior change. Do not invent APIs, dependencies, configuration, database fields, or test results. Keep the public interface stable and avoid unrelated formatting churn. First identify the function or module’s responsibilities, input and output contracts, side effects, mutation, error paths, and hidden assumptions. Then return:
1. A concise refactor plan ordered from lowest-risk to highest-risk, with any ambiguity called out. 2. The revised code in one code block, complete enough to replace the supplied unit. Preserve language idioms and existing error-handling conventions. 3. A change ledger listing each meaningful change, the maintainability problem it addresses, and why behavior should remain the same. 4. Tests to add or update, including ordinary behavior, boundary values, null or empty inputs where valid, invalid input, error propagation, and one regression test for the most likely failure. 5. A manual verification checklist for callers, logging, async behavior, resource cleanup, and performance-sensitive loops if relevant. Prefer extracting a function only when it has a clear name, stable inputs, and one job. Preserve evaluation order when side effects may matter. Do not replace readable domain terms with generic names. Before answering, check that all return paths remain covered and that the refactor does not change exception behavior, async timing, or mutation semantics without explicitly flagging it. Ask up to three clarifying questions only if a required input is missing.
Fill in
| Placeholder | What to enter | Example |
|---|---|---|
| [LANGUAGE AND VERSION] | Name the language, version, framework, and any relevant linting or formatting conventions. | TypeScript 5.5, Node 20, ESLint with no explicit any; no new packages. |
| [CODE AND CONTEXT] | Paste the code to clean up plus nearby types, helpers, or call-site context needed to understand it. | Function buildInvoiceRows(orders, taxRate) loops through orders, skips canceled orders, mutates each order.total, and returns rows used by the CSV exporter. |
| [CURRENT BEHAVIOR] | Describe what the code must continue to do, its public interface, and known callers. | Keep buildInvoiceRows(orders, taxRate) callable by the exporter; canceled orders are excluded; totals must remain rounded to cents. |
| [CONSTRAINTS AND STYLE] | List compatibility limits, performance requirements, allowed dependencies, and team style rules. | Do not change the exported function name or CSV column order; input orders may be shared with the reporting screen. |
| [TESTS AND EDGE CASES] | Paste relevant tests, failures, production symptoms, and input cases the code must handle. | Existing tests cover one paid order and one canceled order; zero tax, missing line items, and negative adjustments have caused past defects. |
How to use
- Include the surrounding type definitions and one or two callers when a refactor affects data shape or side effects.
- State which behavior is intentional, even if it looks odd, so the cleanup does not erase a business rule.
- Apply the smallest reviewable change first and run existing tests before accepting suggested new tests.
- Follow up with: “Show the smallest possible diff for only the first refactor step and explain any behavior you cannot prove is preserved.”
Variations
Legacy function
Use this when a long function is difficult to change because its behavior is poorly documented.
Analyze this legacy [LANGUAGE] function: [CODE]. Known callers and observed behavior are [CALLERS AND BEHAVIOR]. Propose a characterization-test plan before refactoring. Return the behaviors to lock down, test cases with exact inputs and expected outputs, risky side effects, and a smallest-first extraction sequence. Do not rewrite production code yet. Flag places where expected behavior is unknown rather than guessing. Check that the tests cover normal output, errors, mutation, and ordering.
PR review cleanup
Use this when reviewing a proposed refactor before it is merged.
Review this refactor diff for [LANGUAGE]: [DIFF]. The original behavior and acceptance criteria are [EXPECTED BEHAVIOR]. Look for accidental behavior changes, lost error handling, altered public interfaces, concurrency problems, and tests that no longer prove the intended contract. Return findings ranked by severity, each with file or code reference, why it matters, and a concrete fix. Separate style preferences from correctness issues. Do not assume code outside the diff changed. Check every changed return path and exception path.
Testable design
Use this when cleanup should make a module easier to test without changing its external contract.
Refactor [CODE] in [LANGUAGE] to improve testability while preserving [PUBLIC CONTRACT]. Current hard dependencies and side effects are [DEPENDENCIES]. Existing tests are [TESTS]. Propose a minimal seam for time, network, filesystem, randomness, or persistence only where needed. Return revised code, tests using the seam, and an explanation of why the dependency boundary is appropriate. Do not introduce a framework or dependency injection container unless already present. Check that production defaults preserve current behavior.
Tips
- Write characterization tests before extracting logic from code with unclear behavior; they turn observed quirks into explicit decisions.
- Keep a refactor separate from a feature change in version control, because reviewers need to identify behavioral differences quickly.
- Watch for mutation hidden inside convenience code such as sorting, default assignment, or reused object references.
- In asynchronous code, preserve cancellation, retry, and error propagation paths; a cleaner promise chain can still change when work starts.
FAQ
Can AI safely refactor code without tests?
It can identify risk and draft characterization tests, but it cannot prove behavior preservation without executable evidence. Start by locking down critical paths.
Should a cleanup include renaming everything?
Rename terms that obscure the domain or violate local conventions. Large naming-only churn can hide meaningful changes and complicate review.
How do I know when to split a function?
Split it when a portion has a single purpose, clear inputs, and a useful name. Do not extract code merely to reduce line count.