regent-refactor
Apply a modified REgent spec to an existing codebase (or to a fresh
checkout). The user has edited specs/<module>.spec.md (and/or
inventory/functional-checklist.md, inventory/test-oracle.md,
conventions/*.md) to change intent. This skill rewrites the source
tree so the new spec is satisfied, and proves it by running the
graded test suite (black-box checklist + white-box oracle).
Refactor ≠ rebuild. Refactor preserves intent that the user kept
(unchanged spec sections) and only mutates code where the spec
demands a new behaviour. Rebuild would throw the whole project away.
Read the diff first, mutate surgically.
When to Use
- A spec tree exists and has been edited since the last reverse.
- The user wants the codebase aligned to the edited spec without a
full ground-up rebuild.
- A "shit-mountain" project needs to be brought under a spec —
reverse it (regent-reverse), then refactor it (this skill) one
spec change at a time.
Don't use for:
- First-time spec generation — that is regent-reverse.
- Verifying an unmodified spec — that is regent-build.
- Editing code without a spec to point at — this skill assumes the
intent is captured somewhere in
<spec_dir>.
Inputs
spec_dir (REQUIRED) — path to the edited spec tree.
source_dir (REQUIRED) — path to the existing codebase that
reflects the pre-edit spec. The agent will mutate this in place
(or write to a sibling out_dir, see strategy).
strategy — in-place (default, mutates source_dir after
snapshot) | side-by-side (writes to out_dir for diffing).
Default is in-place because refactor scenarios usually want the
project on disk to stay current.
out_dir — only used with strategy: side-by-side. Default is a
sibling of source_dir named <source_dir>-refactored.
Workflow (MUST follow in order)
1. Diff the spec
Before touching code, identify what changed. The user's edit is
authoritative for intent.
- For each tracked file under
<spec_dir> (especially
specs/*.spec.md, inventory/functional-checklist.md,
inventory/test-oracle.md, conventions/*.md):
- If the file has a
## Edited: or ## Changelog: heading
written by the user, use it.
- Else, do a content diff vs the project history if a
.git is
available under <spec_dir> (REgent specs may be versioned).
- Else, ask the user what changed. Do not guess.
- Record the diff in a working note (in-memory; do not commit a
scratch file unless the user asks).
- Pure-clarification edits are legitimate. If the diff only
adds precision to an existing requirement without changing
inputs, outputs, error paths, or exit codes, classify as
Pure clarification per §2 and skip code edits entirely. The
downstream symbol list (§2) can be empty; that is a passing
outcome, not a skipped one.
2. Classify the change
For each R- / S- / oracle entry the user added, removed, or
edited:
- Behaviour change (R-/S- edit that alters inputs, outputs, or
error paths) → rewrite affected module(s). Example:
greet
now raises on name == "Bot" in addition to empty.
- Conventions change (edit in
conventions/*.md) → adjust
style, imports, error types. Example: use httpx not requests.
- Inventory change (checklist or oracle count shift) → may need
new behaviour, but the spec module sections are the source of
truth for what that behaviour is. If a new oracle entry has no
matching
R-, the spec is incomplete — flag it back to the user
before rewriting code.
- Pure clarification (more precise wording, no semantic shift)
→ no code change needed.
For each affected module, list the specific symbols that must
change, with file:line targets.
3. Snapshot before mutating
If strategy: in-place:
- Run
git status in source_dir. If dirty, stop and ask the user
to commit or stash.
- If clean, snapshot via `git worktree add ../-snapshot
If strategy: side-by-side: copy source_dir to out_dir. The
original source_dir itself is the rollback; no separate snapshot
needed.
4. Spawn the rewriter subagent
Use delegate_task with these properties:
role: leaf
- Goal must contain:
spec_dir, the source dir (or out_dir), the
diff of the spec, the list of symbols that must change from step
2, the test command from <spec_dir>/conventions/dev-env.md.
- The rewriter's job is to edit only the symbols listed in
step 2. It is forbidden to refactor unrelated code, even if the
code looks ugly — that is style, not behaviour, and would defeat
the round-trip audit.
- The rewriter must NOT regenerate code from scratch (unlike
regent-build). It must
read_file → patch → re-run pytest.
- The rewriter's final report must include a diff (before vs after
for each changed symbol) so the user can spot accidental
over-rewriting.
5. Run verification — both grading keys
After the rewriter reports:
- Run the test command from
conventions/dev-env.md. Capture exit
code. (This is the suite the project already has — same as a
manual developer would run.)
- Execute every line of
functional-checklist.md against the
result (re-run each command / import / CLI).
- Execute every
### <symbol> block in test-oracle.md against
the result (call the function with the documented input, check
the documented output).
- ALL THREE must be green: pytest, checklist, oracle.
- Clarification-derived oracle: if the spec edit added a new
R-/S- clause, the rewriter MUST also add an ### <symbol>
block to test-oracle.md (or a scratch verification command) that
exercises the clarification explicitly, even when no code change
was needed. Without this, the clarification is a documented intent
that no test actually pins.
6. Decide
- All three green AND
git diff --stat source_dir out_dir is empty:
this is the clarification-only outcome. Report
"Clarification-only refactor: zero source changes, spec edit is
documented intent only." Treat this as a successful outcome, not
a failure to edit. Show the new oracle entry as the proof that
the clarification is exercised.
- All three green AND the diff is non-empty: state the changed
symbols (file:line diff summary) and confirm the spec edit is
now in the code.
- Anything red → do not auto-rollback. Report which item, the
actual vs expected, and the offending code path. The user
decides whether to: (a) tweak the rewriter's diff, (b) amend the
spec to match the code reality, or (c) roll back the snapshot.
- Rewriter touched code outside its scope → flag the diff.
This is a regression of trust — the rewriter overstepped its
brief. Roll back those edits, retry with a sharper scope.
7. Self-review
Before declaring done:
Common Pitfalls
- Reflavoring everything. The rewriter's mandate is the diff
in step 1. Modules untouched by the diff MUST remain
byte-identical (modulo whitespace) — otherwise the audit breaks.
Grep the diff before sign-off.
- Reading the original repo for inspiration. Refactor is
allowed to read
source_dir (it is the codebase being edited).
It is NOT allowed to look up training-data versions of similar
projects to fill in — that smuggles in intent not in the spec.
- Trusting the rewriter's "I changed it" report without
diffing. Always run
git diff --stat against the snapshot.
The agent can claim it changed 5 lines and actually rewrite
- Adding tests not in the spec. The oracle is the only
white-box grading key. New behaviour the user did not write an
oracle entry for is not graded — adding a "while I'm here" test
is a different skill.
- Skipping the snapshot. A bad refactor on a dirty tree
corrupts the user's history. Snapshot or refuse.
Verification Checklist
One-Shot Recipe
# After regent-reverse produced a spec, the user has edited it.
# Now invoke regent-refactor with:
# spec_dir = ./spec-out/<repo>/spec
# source_dir = /path/to/the/checked-out-repo
# strategy = in-place
# Expect a pass/fail report AND a diff summary that the user can
# eyeball against their spec edit.
1---2name: regent-refactor3description: regent-refactor4---56# regent-refactor78Apply a modified REgent spec to an existing codebase (or to a fresh9checkout). The user has edited `specs/<module>.spec.md` (and/or10`inventory/functional-checklist.md`, `inventory/test-oracle.md`,11`conventions/*.md`) to change intent. This skill rewrites the source12tree so the new spec is satisfied, and proves it by running the13graded test suite (black-box checklist + white-box oracle).1415Refactor ≠ rebuild. Refactor preserves intent that the user kept16(unchanged spec sections) and only mutates code where the spec17demands a new behaviour. Rebuild would throw the whole project away.18Read the diff first, mutate surgically.1920## When to Use2122- A spec tree exists and has been edited since the last reverse.23- The user wants the codebase aligned to the edited spec without a24 full ground-up rebuild.25- A "shit-mountain" project needs to be brought under a spec —26 reverse it (regent-reverse), then refactor it (this skill) one27 spec change at a time.2829**Don't use for**:30- First-time spec generation — that is regent-reverse.31- Verifying an unmodified spec — that is regent-build.32- Editing code without a spec to point at — this skill assumes the33 intent is captured somewhere in `<spec_dir>`.3435## Inputs3637- `spec_dir` (REQUIRED) — path to the **edited** spec tree.38- `source_dir` (REQUIRED) — path to the existing codebase that39 reflects the **pre-edit** spec. The agent will mutate this in place40 (or write to a sibling `out_dir`, see `strategy`).41- `strategy` — `in-place` (default, mutates `source_dir` after42 snapshot) | `side-by-side` (writes to `out_dir` for diffing).43 Default is in-place because refactor scenarios usually want the44 project on disk to stay current.45- `out_dir` — only used with `strategy: side-by-side`. Default is a46 sibling of `source_dir` named `<source_dir>-refactored`.4748## Workflow (MUST follow in order)4950### 1. Diff the spec5152Before touching code, identify what changed. The user's edit is53authoritative for intent.5455- For each tracked file under `<spec_dir>` (especially56 `specs/*.spec.md`, `inventory/functional-checklist.md`,57 `inventory/test-oracle.md`, `conventions/*.md`):58 - If the file has a `## Edited:` or `## Changelog:` heading59 written by the user, use it.60 - Else, do a content diff vs the project history if a `.git` is61 available under `<spec_dir>` (REgent specs may be versioned).62 - Else, ask the user what changed. Do **not** guess.63- Record the diff in a working note (in-memory; do not commit a64 scratch file unless the user asks).65- **Pure-clarification edits are legitimate.** If the diff only66 adds precision to an existing requirement without changing67 inputs, outputs, error paths, or exit codes, classify as68 `Pure clarification` per §2 and skip code edits entirely. The69 downstream symbol list (§2) can be empty; that is a passing70 outcome, not a skipped one.7172### 2. Classify the change7374For each `R-` / `S-` / oracle entry the user added, removed, or75edited:7677- **Behaviour change** (R-/S- edit that alters inputs, outputs, or78 error paths) → rewrite affected module(s). Example: `greet`79 now raises on `name == "Bot"` in addition to empty.80- **Conventions change** (edit in `conventions/*.md`) → adjust81 style, imports, error types. Example: use `httpx` not `requests`.82- **Inventory change** (checklist or oracle count shift) → may need83 new behaviour, but the spec module sections are the source of84 truth for what that behaviour is. If a new oracle entry has no85 matching `R-`, the spec is incomplete — flag it back to the user86 before rewriting code.87- **Pure clarification** (more precise wording, no semantic shift)88 → no code change needed.8990For each affected module, list the **specific** symbols that must91change, with file:line targets.9293### 3. Snapshot before mutating9495If `strategy: in-place`:9697- Run `git status` in `source_dir`. If dirty, stop and ask the user98 to commit or stash.99- If clean, snapshot via `git worktree add ../<source_dir>-snapshot100 <HEAD>~0` OR a tarball. The snapshot is the rollback point if101 this skill corrupts the tree. **Mandatory: snapshot MUST succeed102 before the rewriter is spawned.**103104If `strategy: side-by-side`: copy `source_dir` to `out_dir`. The105original `source_dir` itself is the rollback; no separate snapshot106needed.107108### 4. Spawn the rewriter subagent109110Use `delegate_task` with these properties:111112- `role: leaf`113- Goal must contain: `spec_dir`, the source dir (or `out_dir`), the114 diff of the spec, the list of symbols that must change from step115 2, the test command from `<spec_dir>/conventions/dev-env.md`.116- The rewriter's job is to edit **only** the symbols listed in117 step 2. It is forbidden to refactor unrelated code, even if the118 code looks ugly — that is style, not behaviour, and would defeat119 the round-trip audit.120- The rewriter must NOT regenerate code from scratch (unlike121 regent-build). It must `read_file` → `patch` → re-run pytest.122- The rewriter's final report must include a diff (before vs after123 for each changed symbol) so the user can spot accidental124 over-rewriting.125126### 5. Run verification — both grading keys127128After the rewriter reports:129130- Run the test command from `conventions/dev-env.md`. Capture exit131 code. (This is the suite the project already has — same as a132 manual developer would run.)133- Execute every line of `functional-checklist.md` against the134 result (re-run each command / import / CLI).135- Execute every `### <symbol>` block in `test-oracle.md` against136 the result (call the function with the documented input, check137 the documented output).138- ALL THREE must be green: pytest, checklist, oracle.139- **Clarification-derived oracle:** if the spec edit added a new140 `R-`/`S-` clause, the rewriter MUST also add an `### <symbol>`141 block to `test-oracle.md` (or a scratch verification command) that142 exercises the clarification explicitly, even when no code change143 was needed. Without this, the clarification is a documented intent144 that no test actually pins.145146### 6. Decide147148- **All three green AND `git diff --stat source_dir out_dir` is empty:**149 this is the **clarification-only** outcome. Report150 *"Clarification-only refactor: zero source changes, spec edit is151 documented intent only."* Treat this as a successful outcome, not152 a failure to edit. Show the new oracle entry as the proof that153 the clarification is exercised.154- **All three green AND the diff is non-empty:** state the changed155 symbols (file:line diff summary) and confirm the spec edit is156 now in the code.157- **Anything red** → do not auto-rollback. Report which item, the158 actual vs expected, and the offending code path. The user159 decides whether to: (a) tweak the rewriter's diff, (b) amend the160 spec to match the code reality, or (c) roll back the snapshot.161- **Rewriter touched code outside its scope** → flag the diff.162 This is a regression of trust — the rewriter overstepped its163 brief. Roll back those edits, retry with a sharper scope.164165### 7. Self-review166167Before declaring done:168169- [ ] Step 1 diff is recorded (in memory or scratch file).170- [ ] Step 2 symbol-level change list is recorded.171- [ ] Source tree is in a git checkpoint if in-place was used.172- [ ] All three grading keys (pytest + checklist + oracle) green.173- [ ] Rewriter's diff matches the symbol list. Nothing else.174- [ ] User informed of changed symbols with file:line.175176## Common Pitfalls1771781. **Reflavoring everything.** The rewriter's mandate is the diff179 in step 1. Modules untouched by the diff MUST remain180 byte-identical (modulo whitespace) — otherwise the audit breaks.181 Grep the diff before sign-off.1822. **Reading the original repo for inspiration.** Refactor is183 allowed to read `source_dir` (it is the codebase being edited).184 It is NOT allowed to look up training-data versions of similar185 projects to fill in — that smuggles in intent not in the spec.1863. **Trusting the rewriter's "I changed it" report without187 diffing.** Always run `git diff --stat` against the snapshot.188 The agent can claim it changed 5 lines and actually rewrite189 500.1904. **Adding tests not in the spec.** The oracle is the only191 white-box grading key. New behaviour the user did not write an192 oracle entry for is not graded — adding a "while I'm here" test193 is a different skill.1945. **Skipping the snapshot.** A bad refactor on a dirty tree195 corrupts the user's history. Snapshot or refuse.196197## Verification Checklist198199- [ ] Spec diff is identified by the user, not inferred.200- [ ] Source tree is snapshotted (in-place) or copied (side-by-side).201- [ ] Symbol-level change list matches the spec diff exactly.202- [ ] The rewriter did not touch code outside that list.203- [ ] `pytest` exit code green.204- [ ] Every `- [ ]` line of `functional-checklist.md` verified.205- [ ] Every `### <symbol>` of `test-oracle.md` executed.206- [ ] User received the file:line diff summary.207208## One-Shot Recipe209210```bash211# After regent-reverse produced a spec, the user has edited it.212# Now invoke regent-refactor with:213# spec_dir = ./spec-out/<repo>/spec214# source_dir = /path/to/the/checked-out-repo215# strategy = in-place216# Expect a pass/fail report AND a diff summary that the user can217# eyeball against their spec edit.218```