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
unslop
Use when writing or editing prose a person will read, or when text sounds AI-generated.
show-me
Use when asked to show, diagram, or walk through how code fits together or what a change does, or before explaining a multi-file flow in prose.
pr
Use when writing or updating a pull request description, or before running `gh pr create`.
commit
Use when writing a commit message, or before running `git commit`.
write-specs
Spec a feature's observable behavior. Use when asked for requirements, when a request says what the system should do but not how, or to capture what a built system already guarantees. Not for how to build it (write-plan).
write-skills
Write, fix, or audit a skill's frontmatter, trigger description, and body. Use when a skill is asked for, never fires, or fires at the wrong moment. Not for a hook (write-hooks) or the plugin manifest and catalog.