Refactor workflow¶
paredit refactor separates deciding, previewing, writing, and verifying so
that automation can stop at any gate. The full lifecycle for a cross-file
rename looks like this:
# 1. Plan: gates, risk summary, and an ordered step list.
paredit refactor plan --symbol old-name src/core.lisp src/util.lisp
# 2. Preview: exact rewrites, no files touched. --manifest-out writes the
# manifest file and prints its hash, so no extra `status` call is needed.
paredit refactor preview --from old-name --to new-name \
--manifest-out preview.json src/core.lisp src/util.lisp
# 3. Review the manifest without writing.
paredit refactor check --manifest preview.json
paredit refactor status --manifest preview.json
paredit refactor diff --manifest preview.json
# 4. Apply the reviewed manifest with hash guards (hash printed by step 2).
paredit refactor apply --manifest preview.json \
--expect-manifest-hash "$HASH" --write
# 5. Verify post-conditions.
paredit refactor verify --symbol old-name --new-symbol new-name \
--phase post src/core.lisp src/util.lisp
Plan output is a contract¶
paredit refactor plan emits JSON with a decision block
(status, next_action, safe_to_automate), gates with
blocks_automation flags, a risk_summary, and an ordered steps array
whose entries carry runnable command strings. An agent can execute the plan
literally: run each step in order and stop when a gate blocks automation or a
step exits non-zero.
risk_summary.overall_risk collapses every gate's level and blocking flag
into the one axis a decision actually needs: "clean" (nothing found),
"advisory" (something found, but nothing blocks automation), or
"blocking" (at least one gate that does). Any blocking gate outranks every
advisory one regardless of severity level, since one blocking gate is enough
to stop unattended editing on its own.
Policy flags such as --require-definitions, --require-references, and
--fail-on-blocking-gate turn advisory checks into hard failures, which makes
plan usable as a CI gate on its own.
Preview manifests and hash guards¶
preview and workspace-preview print a manifest describing every byte-exact
edit. apply refuses to write when:
- the manifest hash does not match
--expect-manifest-hash; - a target file changed on disk since the preview was generated; or
- any rewritten output no longer parses.
This means a manifest can be produced in one CI job, reviewed as an artifact, and applied in a separate controlled job without trusting the intermediate steps.
Direct refactorings still gate writes¶
Named refactorings such as rename-function, extract-function, or
add-function-parameter run in plan mode by default and only modify files
when --write is passed after their own validation gates pass. Symbol-oriented
rewrites never touch strings or comments, and Common Lisp scope-aware
refactors preserve flet/labels/macrolet/symbol-macrolet binding
boundaries.
Workspace scope¶
For repository-wide changes, start with discovery and stay inside the same lifecycle:
paredit inspect workspace --output json .
paredit refactor workspace-plan --symbol old-name .
paredit refactor workspace-preview --from old-name --to new-name . > preview.json
paredit refactor workspace-execute --from old-name --to new-name --write .
workspace-execute wraps preview gates and post-write verification into one
command for cases where a human already reviewed the plan.