{"slug":"refactor-11","title":"refactor","summary":"Restructure existing code without changing its behavior, through a test-gated refactoring loop: a named target, a green suite over that target before any edit, a planned sequence of small named refactorings, and the full suite re-run after every step. Use when the user wants to r","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-10-15T13:11:59.206465Z","repo":{"url":"https://github.com/testdouble/han","stars":303,"forks":24,"license":"MIT","updatedAt":"2026-10-14T20:22:28Z"},"bodyHtml":"<hr>\n<h2>name: refactor\ndescription: &gt;\nRestructure existing code without changing its behavior, through a test-gated refactoring loop: a named target, a\ngreen suite over that target before any edit, a planned sequence of small named refactorings, and the full suite\nre-run after every step. Use when the user wants to refactor, restructure, clean up, simplify, or improve the design\nof existing code, or to apply refactoring recommendations from a code-review or architectural-analysis report. This\nskill changes code; it does not review code (use code-review), assess architecture (use architectural-analysis), plan\na multi-module restructure before executing it (use plan-a-change), map domain boundaries before restructuring along\nthem (use ddd-analysis), or build new behavior test-first (use tdd). Do not use it on code inside an active tdd loop;\nthe refactor step of tdd owns that cleanup. Runs its planned sequence to completion without pausing for review; to review each named\nrefactoring as it lands, use pairing.\nargument-hint: \"[file, module, named smell, or a path to review findings]\"\nallowed-tools:\nRead, Write, Edit, Glob, Grep, Bash(git *), Bash(find *), Bash(npm *), Bash(npx *), Bash(pnpm *), Bash(yarn *),\nBash(pytest *), Bash(python3 *), Bash(go *), Bash(cargo *), Bash(make *), Bash(bundle *), Bash(rake *),\nBash(bash \"$/scripts/han-config-dir.sh\")</h2>\n<h2>Project Context</h2>\n<ul>\n<li>git installed: !<code>which git 2&gt;/dev/null || echo \"not installed\"</code></li>\n<li>current branch: !<code>git branch --show-current 2&gt;/dev/null || echo unknown</code></li>\n<li>working tree: !<code>git status --porcelain 2&gt;/dev/null | head -5</code></li>\n<li>CLAUDE.md: !<code>find . -maxdepth 1 -name \"CLAUDE.md\" -type f</code></li>\n<li>project-discovery.md: !<code>find . -maxdepth 3 -name \"project-discovery.md\" -type f</code></li>\n<li>personal config directory: !<code>bash \"${CLAUDE_PLUGIN_ROOT}/scripts/han-config-dir.sh\" 2&gt;/dev/null || echo \"$HOME/.claude\"</code></li>\n<li>project .han/config.md: !<code>cat .han/config.md 2&gt;/dev/null || echo \"\"</code></li>\n</ul>\n<p>As your first action, use the Read tool on <code>.han/config.md</code> inside the <code>personal config directory</code> path above. A read\nthat returns no file is no personal configuration: continue silently. When that file or the <code>project .han/config.md</code>\nprobe supplies content, apply it per <a href=\"../../references/config-rule.md\">config-rule.md</a>, which governs precedence\nbetween the two files, relative-path resolution, and what to do with a file that reads but cannot be used.</p>\n<h2>Constraints (read before anything else)</h2>\n<p>This skill restructures existing production and test code in your working tree. It is an execution skill, not a document\ngenerator. These constraints shape every step and override any instinct to move faster. The canon they derive from, with\nprovenance, is in <a href=\"./references/refactoring-discipline.md\">references/refactoring-discipline.md</a>; pull that reference\nwhen a step needs the full rule or a step feels off.</p>\n<ul>\n<li><strong>Behavior preservation is the definition.</strong> A refactoring changes internal structure without changing observable\nbehavior. A change that alters behavior is not a refactoring done badly; it is not a refactoring at all. When a\nplanned step turns out to require a behavior change, it leaves this skill's scope: defer it with a note naming the\nbehavior change it needs.</li>\n<li><strong>Tests are the license to refactor.</strong> No edit until the full suite has been run, observed green, and the target's\nbehavior is covered. If coverage of the target cannot be established, stop and offer the characterization path in the\nreference; never refactor blind.</li>\n<li><strong>Small named steps, green to green.</strong> Each step is one named refactoring with a bounded mechanic (extract function,\nrename, move, inline, and so on), and the suite runs after every step. A red suite after a step means revert the step,\nnot patch forward.</li>\n<li><strong>The declared scope is a contract.</strong> The target named in Step 1 bounds every edit. When a step starts pulling in\nfiles outside that scope, stop, report the spread, and let the user re-scope. Spreading edits are how a refactoring\nsilently becomes a rewrite.</li>\n<li><strong>Never alongside an active tdd loop.</strong> If the working tree shows a red-green cycle in flight (failing tests, a\nhalf-implemented behavior), do not run: the refactor step of <code>/tdd</code> owns cleanup inside the loop, and restructuring\nwhile a test is red violates the two-hats rule both skills share.</li>\n<li><strong>Refactor-only changes.</strong> No behavior fixes, no features, no drive-by bug fixes, even when you spot one. Record what\nyou found and leave it. If the user asks for commits, each commit contains refactoring only.</li>\n<li><strong>YAGNI governs the plan.</strong> Apply <a href=\"../../references/yagni-rule.md\">../../references/yagni-rule.md</a>: every refactoring\nin the plan needs evidence the code has a reason to change (a review finding, named duplication, a confusing read\ndocumented by the user, upcoming work in that area). Removing duplication is the job; adding speculative abstraction,\nconfiguration, or indirection is not. Defer evidence-free items with a reopen trigger.</li>\n</ul>\n<h1>Refactor</h1>\n<h2>Step 1: Bind the Target and Resolve Project Config</h2>\n<p><strong>Bind the target.</strong> Resolve the request to a named target: specific files or directories, a named code smell in a named\nplace, or the refactoring findings in a provided document (a <code>/code-review</code> report, an <code>/architectural-analysis</code> report,\nor equivalent). When a findings document is given, extract only the refactoring-shaped findings (structural suggestions,\nduplication, naming, coupling) and record each finding's ID so the summary can trace back to it. If the request is\nopen-ended (\"clean up the codebase\", \"improve quality\") with no named target, ask the user for one before doing\nanything: open-ended refactoring runs are the documented failure mode this skill exists to avoid, and a wrong guess here\nburns the whole run.</p>\n<p><strong>Resolve commands.</strong> Read CLAUDE.md's <code>## Project Discovery</code> section for the test command (under\n<code>### Commands and Tests</code>), the lint command, the build command, language, and framework. If absent, fall back to\n<code>project-discovery.md</code>. If still absent, run <code>${CLAUDE_SKILL_DIR}/scripts/detect-refactor-context.sh</code> and parse its\noutput for git state and manifest-inferred commands. A missing test command is a hard blocker: exhaust inference, then\nask the user, because this skill cannot run without a way to verify behavior. Also note any type-check command the\nproject has; where one exists it runs alongside the tests as a second behavior-preservation check.</p>\n<p><strong>Resolve standards and decisions.</strong> Resolve the coding-standards directory and ADR directory the same way: CLAUDE.md's\n<code>## Project Discovery</code> section, then <code>project-discovery.md</code>, then Glob defaults (<code>docs/</code>, <code>docs/adr/</code>,\n<code>docs/coding-standards/</code>, <code>docs/decisions/</code>). Also check <code>CLAUDE.md</code> and <code>AGENTS.md</code> for inline standards. Read the\nstandards and ADRs whose titles, paths, or one-line summaries indicate they govern the target area; cap at five\ndocuments. The target's restructured form must conform to these. If none exist, state that plainly and infer conventions\nfrom the surrounding code.</p>\n<h2>Step 2: Establish the Safety Net</h2>\n<p><strong>Check the tree.</strong> If <code>working tree</code> in Project Context shows failing mid-cycle work or the user describes an in-flight\ntdd loop on this code, stop and say why (the never-alongside-tdd constraint). Uncommitted but complete work is fine;\nrecommend committing it first so refactoring diffs stay clean, then proceed.</p>\n<p><strong>Run the full suite.</strong> Run the resolved test command with Bash. <strong>Paste the runner's summary line.</strong> If anything is\nred, stop: a red suite is not a license to refactor. Report the failures and recommend fixing them first (via\n<code>/investigate</code> or <code>/tdd</code>), or re-scoping the target away from the broken area.</p>\n<p><strong>Establish coverage of the target.</strong> Confirm the target's observable behavior is exercised by the suite: find the tests\nthat drive the target (Glob and Grep for the target's public symbols in test files), and run them scoped if the runner\nsupports it. State plainly which behaviors are covered and which are not. If the target has no meaningful coverage, stop\nand offer two ways forward, and wait for the user's choice: narrow the target to the covered part, or write\ncharacterization tests first using the protocol in\n<a href=\"./references/refactoring-discipline.md\">references/refactoring-discipline.md</a>. Characterization tests pin current\nobserved behavior (including current bugs) and are a lower-confidence net than intent-written tests; say so in the\nreport.</p>\n<h2>Step 3: Plan the Sequence Before Editing</h2>\n<p>Plan the whole run before the first edit. Produce a numbered refactoring plan where each item is:</p>\n<ul>\n<li><strong>One named refactoring</strong> (the vocabulary is in the reference; use the project's language idioms, not Java mechanics),\napplied to a named place.</li>\n<li><strong>The evidence for it.</strong> The finding ID, the duplicated code, the standard or ADR it brings the code into conformance\nwith, or the user's stated pain. Items without evidence are deferred per the YAGNI constraint, with a reopen trigger,\nnever silently dropped.</li>\n<li><strong>Its expected blast radius.</strong> The files the step should touch. This is what the scope stop-rule in Step 4 checks\nagainst.</li>\n</ul>\n<p>Order the plan so each step leaves the code releasable: small, independent steps first, dependent steps after the steps\nthey need. Report the plan to the user, then continue immediately; this is a report, not a gate. The one exception: if\nthe request explicitly asks to review or approve the plan first, wait for approval.</p>\n<h2>Step 4: Execute, One Named Refactoring at a Time</h2>\n<p>Take the plan items in order. For each:</p>\n<ol>\n<li><p><strong>Make the one change.</strong> Apply the single named refactoring, touching only the files in its declared blast radius.\nStay in the refactoring hat: no behavior fixes, no extras spotted along the way (record them for the summary\ninstead).</p>\n</li>\n<li><p><strong>Run the full suite</strong> (and the type-check command where one was resolved). <strong>Paste the runner's summary line.</strong>\nPaste full output only when something fails or looks unexpected.</p>\n</li>\n<li><p><strong>Green: cross the item off</strong> and move to the next.</p>\n<p><strong>Running collaboratively.</strong> When the request asks to review each named refactoring as it lands, which is what\n<code>pairing</code> does when it hands work here, stop at this point and hand control back instead of continuing. Present the\nstop in the shape <a href=\"../../references/collaborative-stop-rule.md\">collaborative-stop-rule.md</a> specifies. Absent such a\nrequest, continue as below; an ordinary invocation is unchanged.</p>\n</li>\n<li><p><strong>Red: revert this step.</strong> When git is available and the tree was clean at start, <code>git checkout</code>/<code>git restore</code> the\ntouched files. When git is absent, or the tree was already dirty at start, undo the edits directly instead, so\nreverting this step does not discard the user's other work. Do not patch forward over a red suite; a failed step\nmeans the mechanic was unsafe or the coverage was thinner than it looked. Diagnose, then either retry with a smaller\nstep or defer the item with what you learned.</p>\n</li>\n<li><p><strong>Stop rules.</strong> If the step needed files outside its declared blast radius, or the only way to make it work changes\nobservable behavior, or two consecutive plan items have been reverted: stop, report where things stand (everything\nalready applied is green and stands), and let the user re-scope.</p>\n</li>\n</ol>\n<p>If the user asked for commits, commit after each green step or each logical group of green steps, message naming the\nrefactoring applied, refactoring only.</p>\n<h2>Step 5: Final Verification and Summary</h2>\n<p>Run the full test suite, the lint command, and the build command from Step 1. <strong>Paste the summary line from each.</strong> If\nlint or build fails on code this skill touched, fix it and re-run; that is in scope.</p>\n<p>Summarize for the user:</p>\n<ul>\n<li>Each refactoring applied, named, with the evidence it rested on (finding IDs from the source report where one was\nused) and the files it touched.</li>\n<li>Deferred items: the YAGNI deferrals with reopen triggers, any items deferred because they required behavior changes,\nand any stop-rule exits.</li>\n<li>Anything spotted but deliberately left alone (bugs, smells outside scope), so it can feed <code>/issue-triage</code> or the next\n<code>/code-review</code>.</li>\n<li>Which coding standards and ADRs the restructured code now conforms to.</li>\n<li>Final test, lint, and build status, with output shown, not asserted.</li>\n<li>If characterization tests were written, say so and recommend replacing them with intent-written tests over time.</li>\n</ul>\n","files":[{"path":"references/refactoring-discipline.md","sizeBytes":6945,"isText":true},{"path":"scripts/detect-refactor-context.sh","sizeBytes":3295,"isText":true},{"path":"SKILL.md","sizeBytes":12461,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-10-15T13:12:36.065023Z","sha256":"BEBEAE952404E3EBC06298E5750D31E245F9942EC9D836D07457570B9BE5970A","sizeBytes":9749},"review":null,"source":{"repositoryUrl":"https://github.com/testdouble/han","path":"han-coding/skills/refactor","license":"MIT","commit":"abba73a773528905a8f3d15956029394746e5c7f","subtreeSha":"63AA9F1C153EC0A0129C94015C79A3B0C01F8480771B3DB48428840DA4E9FD44","lastSyncedAt":"2026-10-15T13:11:53.672149Z"},"reviewedAt":"2026-10-15T13:14:01.024258Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/testdouble/han/tree/main/han-coding/skills/refactor"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install testdouble-han@llmmart"},{"target":"git","command":"git clone https://github.com/testdouble/han.git"}]}