AGENT SKILL

refactor

Refactor without changing behavior. Use when asked to restructure, extract, move, or split code, or when a review hands over a structural fix. Not for readability (clean-code) or adding behavior (write-plan, tdd).

License 许可
MIT
最近更新
2026-11-15
Stars
★ 0
Forks
0

01 前言 Front Matter

name
refactor
description
Refactor without changing behavior. Use when asked to restructure, extract, move, or split code, or when a review hands over a structural fix. Not for readability (clean-code) or adding behavior (write-plan, tdd).

03 SKILL.md 正文

Refactor

Move structure with behavior locked. The net is a test green before the move and green after — never a judgment that "this looks the same."

Behavior is settled here, and that is what lets you touch structure without a spec or a plan. You enter at a behavior-preserving structure change, asked for directly or handed over by qc, architecture-audit, clean-code, or tdd's post-green pass. You bypass write-specs and write-plan — there is no new behavior to specify or route.

A refactor that changes observable behavior is a bug wearing a refactor's clothes. The test net is what catches it.

Steps

1. Pin the behavior

Before any structure changes, establish a green net that captures the behavior under the move.

  • A passing test already covers the behavior → use it.
  • No test covers it → write a characterization test that captures the behavior as it is today, not as it should be, and run it green. This is not red-green: the test encodes current behavior, bugs and all, because the move must not change it.
  • No runnable check exists at all — no test runner, no script, no REPL command that exercises the target → wire the runner the language ships with or the repo already depends on, then write the characterization test above. Adding a new dependency is the user's call: ask first, and if they decline, state the absence and stop. You do not move structure blind.
  • The target has no observable behavior — nothing calls it, or every call is itself dead → flag it dead and hand to write-plan for deletion. There is nothing to characterize.

Each pinning test, reused or new, asserts a value rather than a shape, per Writing the test. For a characterization test, the known-good literal is today's output, captured by running the code once. Before the first move, prove each pinning test can fail: change its expected literal, run it red, restore the literal, run it green. A test that stays green with its literal changed is no net; rewrite its assertion until it goes red.

Done when a green test pins every behavior the move touches and each one has gone red with its expected literal changed, or the target is flagged dead, or the user declined a runner.

2. Move the structure

Execute the move: a rename, an extraction, or a reorder — the vocabulary clean-code uses, at the scale qc would recommend. One move at a time; run the net after each. Green stays green between moves.

A move that cannot finish with the net green stops here — it is not behavior-preserving, and you are at step 3's decline.

Done when the structural move is complete and the net is green after every move in it.

3. Gate behavior

Run the full net — the characterization tests plus every pre-existing test in scope. The behavior captured in step 1 must reproduce exactly.

  • Green → the move held behavior. Proceed.
  • Red → the move changed behavior. Revert that move. Do not adjust the test to make it pass: a test edited to match new behavior is the net disabled, and the red is the net doing its job.

A move that needs new or changed behavior to make sense — a new branch, a different return on some input, behavior that was not there before — is declined, not forced. That is not a refactor; it is new behavior, and it enters the chain at write-plan, worked as tdd. Hand it over with the structural goal named; the plan can carry both.

Done when the net is green end to end and no move in this pass introduced behavior, or the behavior-changing move has been declined and handed to write-plan.

4. Hand to qc

Structure moved, behavior held, net green: hand the change to qc to review the new structure — the move may be behavior-preserving and still be ugly, mislayered, or indirected past readability. qc is the axis for that; refactor is not.

Done when the change is handed to qc with the move named and the net result recorded.

Referencing

Where an effort directory exists for the change, the refactor records its net and result there as <name>.refactor.md, under the referencing convention. Where none exists, the result goes to chat and the net is the repo's tests; refactor bypasses write-specs and write-plan, so it never creates one.

pinned behavior [`db.test.ts:12`](../../../src/db.test.ts#L12)
handed to qc [`qc`](../qc/SKILL.md)

04 同仓库更多 Skills