| name | refactor |
| description | Automated code smell detection and remediation. Detects code smells using a hybrid approach (linters + LLM), fixes session-introduced smells immediately, and creates Worklog work items for pre-existing smells with structured REFACTOR comments to prevent duplicates. |
Refactor
Overview
The refactor skill provides automated code smell detection and remediation for
agent-implemented code changes. It runs after implementation completes (but
before the final commit) to identify and address code quality issues.
Key Concepts
- Session boundary: Only files modified in the current session are analyzed (git diff against parent branch)
- Hybrid detection: Combines linter-based mechanical checks with LLM-based design/architectural analysis
- Auto-fix: Auto-fixable linters (ruff, eslint) resolve mechanical issues in-place before detection
- Pre-existing smells: Non-auto-fixable issues become Worklog work items with REFACTOR comments to prevent duplicates
Architecture
refactor/
โโโ SKILL.md # This file
โโโ __init__.py # Package init
โโโ session_boundary.py # Git diff session boundary detection
โโโ smell_detection.py # Hybrid linter + LLM smell detection
โโโ workitem_creation.py # Worklog work item creation
โโโ comment_injection.py # Structured REFACTOR comment injection
โโโ scripts/
โโโ __init__.py # Scripts package init
โโโ refactor.py # Main orchestration script
When To Use
- As a post-implementation quality check in the implement
workflow.
- Manually via
/refactor <work-item-id> to run code smell analysis on
session changes.
- Integrated into CI/CD pipelines for automated code quality gates.
Verification
Refactoring changes must be verified against the full project test suite
before completion. Run the suite via the
test skill (/skill:test โ run โ triage โ evaluate โ
loop until green), following the quiet pytest contract, so refactor fixes do
not silently break behavior.
Status Management
The refactor script manages work item status automatically via the shared
StatusLifecycle context manager when invoked with a work-item-id.
- On entry: Status is set to
in_progress
- On success: Original status is restored (
restore_on_exit=True โ this
read-only skill never advances the item to completed, which wl only
allows for in_review/done stages)
- On error: Status is restored to its original value
No manual wl update --status commands are needed โ the script handles
lifecycle transparently. Stage is NOT modified by this skill. The item is
never left in in_progress when the script exits.
In --dry-run mode, status management is skipped entirely, since no
changes are being made and no work item context is expected.
Invocation
python -m skill.refactor.scripts.refactor [<work-item-id>] [--no-llm] [--no-linter] [--dry-run] [--json] [--parent-branch <branch>] [--config <path>]
- If a
<work-item-id> is provided and --dry-run is not set, the script will manage the work item's status using StatusLifecycle.
- If no
<work-item-id> is provided or --dry-run is set, the script runs without any work item status interaction.
Usage
Invocation
python -m skill.refactor.scripts.refactor [<work-item-id>] [--no-llm] [--no-linter] [--dry-run] [--json] [--parent-branch <branch>] [--config <path>]
Agent invocation: /refactor <work-item-id>
Output
Structured report with: files analyzed, smells detected, smells fixed, work items created, REFACTOR comments injected.
Configuration
Command-line flags
| Flag | Description |
|---|
--no-llm | Disable LLM-based detection (linter only) |
--no-linter | Disable linter detection (LLM only) |
--dry-run | Show what would be changed without making changes |
--json | Output results in JSON format |
--parent-branch <branch> | Override parent branch for diff (default: dev) |
--config <path> | Path to custom .refactor.json config file |
.refactor.json Configuration
Example config (project root):
{
"linter": { "enabled": true, "severity_overrides": {} },
"llm": { "enabled": true, "model": "default", "temperature": 0.1, "max_tokens": 2000 },
"severity_mapping": { "critical": "high", "high": "high", "medium": "medium", "low": "low" },
"smell_types": ["unused_import"
Smell Types
| Code / Type | Description | Detection | Severity |
|---|
| F401 | Unused import | Linter | Critical |
| F841 | Unused variable | Linter | Critical |
| E302 | Missing blank lines | Linter | High |
| C901 | Complex function (mccabe) | Linter | Low |
| unused_function | Function defined but never called | LLM | Medium |
| magic_number | Numeric literal without named constant | LLM | Low |
| god_class | Class with too many responsibilities | LLM | High |
| feature_envy | Method overly interested in another class | LLM | Medium |
| shotgun_surgery | Single change requires many file modifications | LLM | Medium |
| inappropriate_intimacy | Classes that know too much about each other | LLM | Medium |
REFACTOR Comments
When a pre-existing smell is detected, a structured REFACTOR comment is injected:
<!-- REFACTOR-SA-0MOCK9999
smell: <type>
severity: <level>
description: <text>
-->
Comment delimiters vary by file type โ # for Python, // for JS/TS, <!-- --> for HTML/Markdown.
Error Handling
- Missing git repo: Returns empty session (no files to analyze)
- No linter: Falls back to LLM-only detection
- No LLM client: Falls back to linter-only detection
- File permission errors: Skips file, logs warning
- Binary files: Handled gracefully
Related Skills