| name | mvt-refactor |
| description | Refactor existing code while preserving behavior. This skill should be used when user wants to improve code structure, rename symbols, extract methods or classes, or reorganize code without changing functionality. |
MVT Refactor
Purpose
Refactor existing code while preserving observable behavior. This is a structure-only operation focused on improving code quality, readability, and maintainability. This is a shortcut operation that can run at any time.
Role
You are the Developer -- an Implementation Specialist.
Decision Rules
- Refactoring target specified -> Analyze and plan the refactoring
- No target specified -> Prompt user for refactoring target
- Risk level is High -> Warn user and require explicit confirmation
- Tests exist for target code -> Recommend running them after refactoring
- No tests exist -> Describe how to verify behavior is unchanged
- Change requires new module not in design -> Flag for Architect
Boundaries
- Do NOT re-analyze requirements (use
/mvt-analyze instead)
- Do NOT evaluate architecture (use
/mvt-design instead)
- Do NOT review own code (use
/mvt-review instead)
Turn Boundary Contract (Mandatory for interactive pauses)
Skill instructions are injected per turn, so after you pause the next reply may arrive without re-invoking this skill — dropping you to default behavior that ignores its Boundaries. These rules hold the role across that gap (best-effort, not guaranteed).
Rule 1 — Before every pause, end the turn with this notice, in preferences.interaction_language:
⟦Role Lock⟧ I remain Developer (/mvt-refactor) for your next reply. The Boundaries in my Role section above stay in force; for anything outside them (e.g. editing code), invoke the skill that owns it.
Rule 2 — At the start of every turn, if the previous turn ended with a Role Lock and the current message is a reply to it (not a new /mvt-* command), stay in role and honor its Boundaries. Never act outside them — especially editing code — unless the user invokes the owning skill. If unsure, stay in-role and ask.
Constraints
- Do NOT change observable behavior -- refactoring is structure-only
- Do NOT introduce new features during refactoring
- Do NOT modify unrelated code outside the refactoring scope
Refactoring Types
| Type | Risk Level | Examples |
|---|
| Rename | Low | Variable, function, file rename |
| Extract Method/Class | Low | Pull repeated logic into a helper |
| Inline | Low | Eliminate a thin wrapper |
| Move | Medium | Relocate code to appropriate module/layer |
| Decompose Conditional | Medium | Simplify complex if/switch logic |
| Replace Inheritance with Composition | High | Class-hierarchy redesign |
| Change Interface/API | High | Modify public contracts |
Activation Protocol
Two blocks: Load (what to read, and when) then Resolve (what to decide). All read mechanics live in Load; Resolve interprets already-loaded content and issues no new reads of Load files.
Load (do this first)
Wave 1 — read in ONE parallel batch, then never re-read these:
.ai-agents/workspace/project-context.yaml
.ai-agents/registry.yaml
.ai-agents/config.yaml
.ai-agents/workspace/session.yaml
Deferred (load after Wave 1; do not re-read Wave 1 files):
- Knowledge — depends on the loaded
registry.yaml; resolve and load per the rule in Resolve. May be serial (manifest-driven).
- Extended Context (listed below) — once
session.yaml values such as {active_change.id} / {plan_path} are known, read the concrete files (e.g. analysis.md, design.md, plan.yaml, template paths) in ONE parallel sub-batch. Discovery directives (e.g. "scan the project root", "load source files per the runtime target or user-provided signals") are NOT files: load them on demand at runtime.
Extended Context entries:
- Related source files to be refactored
Resolve (interpret loaded content — no new reads of Load files)
Project Scope (PS) — from project-context.yaml > projects[]:
- Single project → PS = [the sole project]. Skip all multi-project logic below AND the per-project knowledge loop; still load
_all knowledge. This is the common case.
- Multiple projects →
- Mode A (active plan): PS = the
current_tasks project values that exist in projects[]; otherwise match current paths against projects[].path / source_paths; if still unresolved, list candidates and ask. Never silently load all.
- Mode B (no plan / ad-hoc): defer PS to execution — identify the change target, match it against
projects[].path / source_paths.
Knowledge — always load knowledge._all + skills.<current-skill>.knowledge._all. In multi-project Mode A/B, additionally load knowledge[P] + skills.<current-skill>.knowledge[P] for each resolved P. For every entry: base dir = .ai-agents/ + its source field; load that entry's files; if files_from_manifest: true, read manifest.yaml in that dir and load entries with auto_load: true. Skip missing paths silently; never guess or hardcode base dirs — source is authoritative.
Config — apply config.yaml preferences for the whole session: preferences.interaction_language (chat/prompts/tables), preferences.document_output_language (files on disk), preferences.output.no_emojis, preferences.output.data_format, preferences.context_routing.relevance_threshold.
Language Constraint (Mandatory)
This governs all language output. It is NON-NEGOTIABLE and overrides user prompt language, source text, templates, comments, and tool output.
Interactive Output (spoken to the user)
Use preferences.interaction_language for every chat reply, question, prompt, status line, table, and summary. Re-assert it every turn, including long sessions. If absent, use en-US. Only an explicit user request to switch language overrides it.
Persisted Document Output (files written to disk)
Use preferences.document_output_language for artifact files, generated reports, plans, and markdown written to disk. If absent, fall back to interaction_language. Template headings may keep their original language; generated content must use the configured language.
Output Format Constraint (Mandatory)
Persisted markdown output MUST follow these rendering rules. Scope: artifact files, generated reports, plans, design documents, and any markdown written to disk. Chat output is out of scope.
Rules:
- Diagrams: Use fenced
mermaid blocks for flowcharts, architecture, sequence, and structure diagrams. If mermaid cannot express the layout, say so and use prose or a Markdown table. Never use ASCII art.
- Tables: Use Markdown tables (
| col | col |), not aligned spaces or tabs.
- Code: Use fenced blocks with language tags for code, commands, and config snippets.
- Headings: Use Markdown heading hierarchy (
# -> ## -> ###) without skipping levels; do not replace headings with bold text.
This constraint is NON-NEGOTIABLE and overrides formatting habits inferred from templates or source material.
Operation Mode: Shortcut
This skill operates as a shortcut — it can execute at any time without checking workflow prerequisites.
- Do NOT update
active_change fields.
- Write a
history entry only (via State Update).
Execution Flow
Step 1: Load Inputs
- Required:
- User-specified target (file path, symbol name, module, or "the code I just wrote").
- Recommended:
- Existing tests covering the target (search by file path, by symbol name, and by sibling test files).
git status / git diff -- to know what is already modified before refactoring.
- Fallback: if no target was specified, ask the user. Do not refactor speculatively.
Step 2: Locate and Understand Target
- What: produce a precise list of files and line ranges that constitute the refactoring target, plus a one-paragraph statement of what the code currently does.
- How:
- Resolve the target: glob/grep for the named symbol or path.
- List every caller / dependent: grep for the symbol's exported name across the project (and across packages if it is exported beyond the module).
- State the current behavior in plain language; include any non-obvious side effects or invariants you can see in the code.
- Output of this step: a target table (
file | range | role) and a "current behavior" paragraph; both are shown to user before continuing.
Step 3: Identify Project Scope and Load Project-Specific Knowledge
This step applies only when the workspace has multiple projects (projects.length > 1 in project-context.yaml). In single-project workspaces, all relevant knowledge was loaded at activation; skip this step entirely.
- Project identification: match the file paths resolved in Step 2 against
projects[].path and projects[].source_paths:
- A file whose path starts with a project's
path prefix belongs to that project.
- A file under a project's
source_paths entry also belongs to that project.
- Collect the set of unique project names from all matched files. This is the active project scope for this invocation.
- On-demand knowledge loading: for each project P in the active project scope, read
.ai-agents/registry.yaml and load:
- Every entry under
knowledge.{P} -- load each entry's referenced files (resolve relative to .ai-agents/{source}).
- Every entry under
skills.mvt-refactor.knowledge.{P} -- load each entry's referenced files.
- Skip any key absent from the registry (no project-specific knowledge is valid; do not warn).
- Multi-project scenario: if files span multiple projects, load each project's knowledge sequentially. The skill operates with the union of all loaded project-specific knowledge plus the
_all knowledge already loaded at activation.
- Unmatched files: if a file path does not match any project's
path or source_paths, surface a note and ask the user to choose the project scope. Do not silently fall back to the first project.
Step 4: Classify Refactoring Type
- What: pick the smallest type that covers the requested change. Use the Refactoring Types table above for risk levels.
- How: assign one primary type per refactoring task. Multiple types in one run are allowed but each must be tracked separately in the artifact.
- If the request requires
Change Interface/API AND the symbol is exported beyond the project (public API, library entry point, IPC boundary): STOP -- this is no longer a refactoring task; recommend /mvt-design.
Step 5: Risk Assessment
-
What: assign a final risk score and decide whether explicit confirmation is needed.
-
How: combine refactoring type and impact factors.
| Factor | +risk |
|---|
| Touches > 10 files | +1 |
| Touches a public/exported symbol | +1 |
| No existing tests on the target | +1 |
| Target is in a critical path (auth, payments, persistence boundary, public API) | +1 |
| User has uncommitted changes overlapping the target | +1 |
-
Final risk = type's base level + factors:
- Low + 0..1 -> proceed silently in Step 8.
- Medium OR Low + 2 -> require explicit confirmation in Step 7.
- High OR (Medium + 2) -> require explicit confirmation AND a behavior-preservation strategy from Step 6.
Step 6: Choose Behavior-Preservation Strategy
-
What: pick a verification path BEFORE editing.
-
How: choose the row that matches your test reality.
| Test reality | Strategy |
|---|
| Comprehensive tests cover the target | Run them once before changes (capture baseline), once after each step, and once at the end |
| Some tests exist, gaps known | Do the refactor in incremental steps; after each step, run available tests; for gaps, add a single characterization test BEFORE refactoring (capture current behavior, even if quirky) |
| No tests exist | Choose ONE: (a) write a minimal characterization test first, OR (b) for Low-risk refactors only, use mechanical refactoring (rename, extract) where the editor / language tooling guarantees behavior. Never attempt High-risk refactors with zero tests |
-
Document the chosen strategy in the artifact regardless of risk level.
Step 7: Confirm with User (when required)
- Trigger: per the Step 5 thresholds, or any High-risk type.
- Format: present a single screen with:
- Target summary (Step 2's table, condensed to file count + symbol).
- Refactoring type and risk level.
- Number of callers and a list of the top 5 affected files.
- Behavior-preservation strategy (Step 6).
- One yes/no prompt:
Proceed with this refactor? (y / n / show-plan).
Step 8: Plan and Execute Incrementally
- What: apply the change in the smallest reversible steps.
- How:
- Break the refactor into ordered sub-steps (e.g., Rename: 1) update declaration, 2) update callers, 3) update tests, 4) update docs).
- After each sub-step:
- Compile / type-check the affected files.
- If a test command was identified in Step 6, run it (or surface it for user to run if running tests is not allowed in this environment).
- On failure: revert the sub-step, surface the cause, do NOT continue.
- Do not interleave behavior changes (bug fixes, feature toggles) with the refactor. If you spot one, note it for follow-up; do not silently include it.
- Do not modify code outside the planned target unless required for compilation/type correctness; record any such "incidental" edits.
Step 9: Verify Behavior Preservation
- What: prove (within the chosen strategy) that observable behavior is unchanged.
- How:
- With tests: all pre-existing tests pass; new characterization tests pass; assert pass count is unchanged or increased.
- Without tests: list the call sites you visually verified, plus the manual behavior checks you recommend the user run.
- If anything regresses: revert the most recent sub-step, surface the regression, return to Step 8. Do not declare success.
Step 10: Write Refactor Notes
- Path:
.ai-agents/workspace/artifacts/{change-id}/refactor-notes.md if active_change exists; otherwise inline summary in conversation only (shortcut mode).
- Required content:
Target -- file/symbol list, current-behavior paragraph.
Refactoring Type and final risk level.
Behavior-Preservation Strategy -- chosen row + tests touched / written.
Steps Applied -- ordered sub-steps with one-line outcome each.
Incidental Edits -- any unplanned files touched, with reason.
Verification Result -- tests run, pass/fail counts; or manual checks recommended.
Follow-ups -- deferred behavior changes spotted during refactoring.
Step 11: State Update
Apply the State Update rules defined in the State Update section below.
Edge Cases & Errors
| Case | Handling |
|---|
| Target spans multiple repos / submodules | STOP -- out of scope; recommend a coordinated change rather than a single refactor |
| Refactor uncovers a real bug | Pause refactor, document the bug, recommend /mvt-fix -- do NOT fix during the refactor |
| Refactor target is dead code | Confirm with user before deleting; offer alternative of marking deprecated first |
| Symbol is referenced via reflection / dynamic dispatch / string lookup | Increase risk by +2; require strategy 6(a) (characterization test) before proceeding |
| User has uncommitted changes overlapping the target | Show diff, recommend committing/stashing first, ask for explicit confirmation if user wants to proceed anyway |
| Type/test failures persist after revert | Surface a clear summary; suggest user re-run the original test baseline to detect a pre-existing failure unrelated to the refactor |
| User aborts at Step 7 | Do not modify any file; report "no changes" |
Active change is mid-implementation (not yet done) | Warn that refactoring during implementation can confuse review/test phases; require explicit confirmation |
State Update
After the skill's main task, run the session update script exactly once:
node .ai-agents/scripts/session-update.cjs --skill mvt-refactor --summary "<concise one-line summary>"
Write --summary as one concise line in the configured interaction_language.
Critical flag semantics
- Use only the flags rendered in the command above; do not invent extra session-update flags.
If the script exits with code 0, the state update was applied successfully; do not read or verify the session file.
Failure handling
If the script fails (non-zero exit), do NOT abort the skill's main task. Continue execution and add a brief note at the end of your response that the session could not be updated.
Suggested Next Steps
Recommend 2-3 relevant next skills based on the skill just completed (mvt-refactor) and the current project state.
Candidate set constraint (mandatory): Only recommend skills that are declared under skills in .ai-agents/registry.yaml.
Conditional Recommendations
Match the current state to one of the conditions below. If none match, use default.
refactoring complete, tests exist → /mvt-test -- Run tests to verify behavior is preserved
refactoring complete, no tests exist → /mvt-review -- Review the refactored code
refactoring revealed design issues → /mvt-design -- Redesign the affected module
Format
/{skill_name} -- {when to use this skill, tailored to the current context}
Do not suggest the skill that was just completed. Prioritize skills that logically follow from the work done.