| name | lsp-refactor |
| description | End-to-end safe refactor workflow — blast-radius analysis, speculative preview, apply to disk, verify build, run affected tests. Inlines lsp-impact + lsp-safe-edit + lsp-verify + lsp-test-correlation into one coordinated sequence. |
| argument-hint | [symbol-or-file] [intent] |
| user-invocable | true |
| allowed-tools | mcp__lsp__blast_radius mcp__lsp__preview_edit mcp__lsp__simulate_chain mcp__lsp__get_diagnostics mcp__lsp__run_build mcp__lsp__run_tests mcp__lsp__get_tests_for_file mcp__lsp__apply_edit mcp__lsp__replace_symbol_body mcp__lsp__open_document mcp__lsp__format_document Edit Write |
| license | MIT |
| compatibility | Requires the agent-lsp MCP server (github.com/blackwell-systems/agent-lsp) |
| metadata | {"required-capabilities":"referencesProvider","optional-capabilities":"documentFormattingProvider","tool_permissions":{"phases":{"blast_radius":{"description":"Phase 1: analyze impact before any edits","allowed":["mcp__lsp__blast_radius","mcp__lsp__go_to_symbol","mcp__lsp__find_references"],"forbidden":["mcp__lsp__apply_edit","mcp__lsp__simulate_*","Edit","Write"]},"speculative_preview":{"description":"Phase 2: simulate edits in memory, compare diagnostics","allowed":["mcp__lsp__open_document","mcp__lsp__get_diagnostics","mcp__lsp__preview_edit","mcp__lsp__simulate_chain"],"forbidden":["mcp__lsp__apply_edit","Edit","Write"]},"apply":{"description":"Phase 3: write changes to disk and format","allowed":["mcp__lsp__apply_edit","mcp__lsp__format_document","Edit","Write"],"forbidden":["mcp__lsp__simulate_*","mcp__lsp__rename_symbol"]},"build_verification":{"description":"Phase 4: check diagnostics and run the build","allowed":["mcp__lsp__get_diagnostics","mcp__lsp__run_build"],"forbidden":["mcp__lsp__apply_edit","Edit","Write"]},"test_execution":{"description":"Phase 5: find and run affected tests","allowed":["mcp__lsp__get_tests_for_file","mcp__lsp__run_tests"],"forbidden":["mcp__lsp__apply_edit","Edit","Write"]}},"global_forbidden":["mcp__lsp__rename_symbol"]}} |
Requires the agent-lsp MCP server.
lsp-refactor
End-to-end safe refactor workflow. Sequences blast-radius analysis, speculative
preview, disk apply, build verification, and targeted test execution in one
coordinated pass.
This skill does NOT replace lsp-safe-edit or lsp-impact.
lsp-safe-edit wraps a single edit with before/after diagnostic comparison —
use it when you need to make one targeted change with careful error diffing.
lsp-impact is read-only blast-radius analysis — use it when you want to
understand scope before deciding whether to proceed.
lsp-refactor sequences ALL four workflows (lsp-impact → lsp-safe-edit →
lsp-verify → lsp-test-correlation) in order. Use it when you know your target
and intent up front and want the complete workflow without switching skills.
Input
- target: symbol name in dot notation (e.g.
"codec.Encode", "Buffer.Reset")
OR file path (e.g. "internal/lsp/client.go")
- intent: description of the change to make (e.g. "rename to ParseConfigV2",
"add a second parameter
timeout time.Duration")
- workspace_root: absolute path to the workspace root
Phase 1 — Blast-Radius Analysis (inlined from lsp-impact)
This phase is mandatory. Do not skip it, even for "small" refactors.
Call mcp__lsp__blast_radius with changed_files set to the file
containing the target symbol. If the user provided a file path directly, use it.
If the user provided a symbol name, resolve the file first (e.g. via
mcp__lsp__go_to_symbol).
mcp__lsp__blast_radius({
"changed_files": ["/abs/path/to/file"],
"include_transitive": false
})
Returns:
affected_symbols — exported symbols with reference counts
test_callers — test files and enclosing test function names
non_test_callers — production call sites
Display:
- Affected symbol count
- Test callers (each with enclosing test function name)
- Non-test callers (each with file:line)
- Total reference count
High blast-radius gate: If the total reference count exceeds 20, STOP and
ask the user to confirm before continuing:
High blast radius: N callers found. Proceed with refactor? [y/n]
If the user answers "n", abort. Do not proceed to Phase 2.
Phase 2 — Speculative Preview (inlined from lsp-safe-edit)
Only reached if Phase 1 blast radius is acceptable (≤ 20 callers, or user confirmed).
2a — Open file and capture baseline diagnostics
mcp__lsp__open_document({ "file_path": "/abs/path/to/file", "language_id": "go" })
mcp__lsp__get_diagnostics({ "file_path": "/abs/path/to/file" })
Store baseline diagnostics as BEFORE.
2b — Speculative simulation
For a single-file change: use preview_edit:
mcp__lsp__preview_edit({
"file_path": "/abs/path/to/file",
"start_line": <N>,
"start_column": <col>,
"end_line": <N>,
"end_column": <col>,
"new_text": "<replacement text>"
})
For a multi-file change (e.g. rename + call site updates): use simulate_chain:
mcp__lsp__simulate_chain({
"workspace_root": "/abs/path/to/workspace",
"language": "go",
"edits": [
{
"file_path": "/abs/path/to/file.go",
"start_line": <N>, "start_column": <col>,
"end_line": <N>, "end_column": <col>,
"new_text": "<replacement>"
}
// additional dependent edits ...
]
})
2c — Evaluate simulation result
Display the speculative result using the Diagnostic Diff Output Format from
references/patterns.md.
Decision:
net_delta | Action |
|---|
| ≤ 0 | Safe. Proceed to Phase 3. |
| > 0 | Abort. Report introduced errors. Do NOT apply to disk. |
If net_delta > 0, stop and show the full list of errors the simulation
introduced. Do not proceed to Phase 3.
Phase 3 — Apply to Disk
Only reached if Phase 2 net_delta <= 0.
Apply the change using the Edit or Write tool. When the edit targets a complete
function or method body, mcp__lsp__replace_symbol_body is an alternative that
resolves the symbol by name and replaces its full range without position math:
mcp__lsp__replace_symbol_body({
"file_path": "/abs/path/to/file",
"symbol_path": "Package.Function",
"new_body": "func Function() error {\n\treturn nil\n}"
})
For edits computed by simulation, mcp__lsp__apply_edit may be used directly if
the simulation returned an edit object:
Edit(file_path: "/abs/path/to/file", old_string: "...", new_string: "...")
For multi-file changes, apply each file's edits before moving to Phase 4.
If any individual apply fails, stop and report before applying remaining files.
After applying, format the changed file(s):
mcp__lsp__format_document({ "file_path": "/abs/path/to/file" })
Apply the returned TextEdit[] via mcp__lsp__apply_edit if non-empty.
Phase 4 — Build Verification (inlined from lsp-verify)
Run in this order — LSP diagnostics first, then the compiler build:
mcp__lsp__get_diagnostics({ "file_path": "/abs/path/to/file" })
mcp__lsp__run_build({ "workspace_root": "/abs/path/to/workspace" })
Decision:
| Result | Action |
|---|
| Diagnostics clean, build passes | Proceed to Phase 5. |
| Diagnostics show new errors | Display errors and stop. Do not proceed to Phase 5. |
| Build fails | Display build output and stop. Do not proceed to Phase 5. |
If build fails, report the full build error output and stop. Test execution
is skipped until build passes.
Phase 5 — Run Affected Tests (inlined from lsp-test-correlation)
For each file changed in Phase 3, find correlated test files:
mcp__lsp__get_tests_for_file({ "file_path": "/abs/path/to/changed/file" })
Deduplicate the resulting test files if multiple source files were changed.
Run only the correlated test files:
mcp__lsp__run_tests({ "workspace_root": "/abs/path/to/workspace", "test_files": [...] })
If no correlated test files are found: note "No test correlation found —
run full suite manually to confirm." Do not attempt to run ./... automatically.
Abort Conditions
The following conditions abort the workflow immediately. Each abort displays the
relevant output before stopping.
- Phase 1: blast radius > 20 callers AND user does not confirm → abort
- Phase 2:
net_delta > 0 (simulation introduced errors) → abort, show errors
- Phase 4: build fails → abort, show build output
- Any phase: LSP tool returns an unexpected error → abort, report tool output verbatim
Output Format
After completing all phases, produce this structured report:
## lsp-refactor Complete
### Phase 1 — Blast Radius
Affected symbols: N
Test callers: M (list each with enclosing test function)
Non-test callers: K
### Phase 2 — Speculative Preview
[Diagnostic Diff Output Format from patterns.md]
net_delta: 0 → safe to apply
### Phase 3 — Applied
Files changed: [list]
### Phase 4 — Build Verification
Diagnostics: N errors (0 new)
Build: PASS
### Phase 5 — Test Results
Test files run: [list]
Result: PASS / FAIL
If the workflow aborted at a phase, report only the phases completed and the
abort reason:
## lsp-refactor Aborted at Phase 2
### Phase 1 — Blast Radius
...
### Phase 2 — Speculative Preview
ABORTED: net_delta: +2 (errors introduced)
Errors:
- file.go:34 — undefined: NewType
- file.go:51 — cannot use int as string
Example
Goal: rename exported function ParseConfig → ParseConfigV2 in pkg/config
Phase 1 — Blast Radius
blast_radius(changed_files=["pkg/config/parser.go"])
→ affected_symbols: 1 (ParseConfig)
→ non_test_callers: 3 (cmd/main.go, internal/app.go, internal/loader.go)
→ test_callers: 1 (pkg/config/parser_test.go — TestParseConfig)
→ total references: 4 — within threshold, proceeding
Phase 2 — Speculative Preview
open_document(file_path="pkg/config/parser.go")
get_diagnostics → BEFORE: 0 errors
simulate_chain(edits: [parser.go rename + 3 call-site updates])
→ cumulative_delta: 0 → safe to apply
Phase 3 — Applied
Edit parser.go: func ParseConfig → func ParseConfigV2
Edit cmd/main.go, internal/app.go, internal/loader.go: update call sites
format_document(parser.go)
Phase 4 — Build Verification
get_diagnostics → 0 errors
run_build → success
Phase 5 — Test Results
get_tests_for_file(parser.go) → pkg/config/parser_test.go
run_tests(test_files=["pkg/config/parser_test.go"]) → PASS
## lsp-refactor Complete
...