Skip to content

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.

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.