Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions .claude/skills/mechanical-refactor-verify/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
---
name: mechanical-refactor-verify
description: Verify mechanical refactoring commits by requiring a reproducible transform script (gist) in the PR description. Use when doing or reviewing file splits, function moves, or module extractions.
user_invocable: true
argument: "[verify <pr_url_or_commit>] — verify an existing PR, or omit to see the workflow guide"
---

# Mechanical Refactor — Reproducible Verification

## Core Principle

The deliverable of a mechanical move (file split, function move, module extraction) is NOT the diff — it is **the script that produces the diff**.
A script is auditable; a diff is not.

## Workflow

Regardless of who did the move (human or agent) and when (before or after committing), the workflow is the same:

### Step 1: Write the transform script to /tmp/

Write the script to `/tmp/transform_<short_description>.py`. **Never write it inside the repo.**

The scaffold (worktree creation, diff check, ruff format, result reporting) lives in `mechanical_refactor_verify_utils.py` next to this skill.

**MANDATORY**: The transform script MUST use `verify_mechanical_refactor()` from the utils module. Do NOT reimplement the verification scaffold — no hand-written worktree management, no hand-written diff checking. The script only defines `transform()` and calls `verify_mechanical_refactor`.

Script template (follow this structure exactly):

```python
#!/usr/bin/env python3
"""Reproducible transform for: <describe the mechanical move>

Run from the repo root: python3 /tmp/transform_<short_description>.py
"""
import sys
from pathlib import Path

sys.path.append(".claude/skills/mechanical-refactor-verify")
from mechanical_refactor_verify_utils import verify_mechanical_refactor, exec_command, git_add_and_commit, dedent

BASE_COMMIT = "<base_sha>"
TARGET_COMMIT = "<pr_mechanical_move_final_sha>"


def transform(dir_root: Path) -> None:
"""Perform the mechanical transformation and commit each step.

Args:
dir_root: Path to the worktree (checked out at BASE_COMMIT).
"""
# --- Step 1: Split source file ---
source = dir_root / "path/to/source.py"
content = source.read_text()
lines = content.splitlines(keepends=True)

splits = [
("path/to/pkg/target_a.py", 1, 50),
("path/to/pkg/target_b.py", 51, 120),
]
for target_path, start, end in splits:
target = dir_root / target_path
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text("".join(lines[start - 1 : end]))

source.unlink()
(dir_root / "path/to/pkg/__init__.py").touch()

git_add_and_commit("mechanical: split source.py", cwd=str(dir_root))

# --- Step 2: Fix imports ---
# <edit files>
# git_add_and_commit("fix imports", cwd=str(dir_root))

# Note: pre-commit run --all-files is run automatically after transform() returns


if __name__ == "__main__":
verify_mechanical_refactor(
base_commit=BASE_COMMIT,
target_commit=TARGET_COMMIT,
transform=transform,
)
```

### Step 2: Run the script from the repo root

```bash
cd <repo_root>
python3 /tmp/transform_<short_description>.py
# Expected: "PASS: transform reproduces the commit exactly."
```

If FAIL, fix the script and re-run until PASS.

### Step 3: Upload gist, delete local file, update PR description

One gist per PR. Do all three:

```bash
# 1. Create gist (or update existing)
gh gist create --public -d "Mechanical refactor transform: <description>" /tmp/transform_<short_description>.py
# Or update: gh gist edit <gist_id> -a /tmp/transform_<short_description>.py

# 2. Delete local file
rm /tmp/transform_<short_description>.py

# 3. Update PR description (paste the block below)
```

PR description must include:

````markdown
## Mechanical Move

Transform script: <gist_url>

### One-click verification

```bash
python3 <(curl -sL <gist_raw_url>)
```
````

### Step 4: PR scope

A mechanical refactor PR must contain **only** mechanical changes (moves, splits, renames, import fixes, formatting). All of these must be reproducible by the transform script.

Semantic changes (new logic, API restructuring, behavior changes) belong in a **separate PR**.

## Verifying an existing PR (`/mechanical-refactor-verify verify`)

1. Find the gist URL and one-click command in the PR description
2. Run the one-click command from the repo root
3. Report: PASS or show the diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""Utilities for mechanical refactor verification scripts.

See SKILL.md for usage and transform script template.
"""

import shlex
import subprocess
import sys
import tempfile
from collections.abc import Callable
from pathlib import Path


def exec_command(cmd: str, cwd: str | None = None, check: bool = True) -> str:
print(f" $ {cmd}", flush=True)
result = subprocess.run(
cmd,
shell=True,
cwd=cwd,
capture_output=True,
text=True,
)
if check and result.returncode != 0:
print(f"FAILED: {result.stderr}", file=sys.stderr)
sys.exit(1)
return result.stdout.strip()


def git_add_and_commit(message: str, cwd: str) -> None:
exec_command(f"git add -A && git commit -m {shlex.quote(message)}", cwd=cwd)


def dedent(text: str, n: int) -> str:
"""Remove exactly n leading spaces from each line."""
lines = text.splitlines(keepends=True)
return "".join(line[n:] if line[:n] == " " * n else line for line in lines)


def verify_mechanical_refactor(
base_commit: str,
target_commit: str,
transform: "Callable[[Path], None]",
) -> None:
repo_root = exec_command("git rev-parse --show-toplevel")
worktree_dir = tempfile.mkdtemp(prefix="verify-mechanical-")
branch_name = f"verify-mechanical-{base_commit[:8]}"

try:
print(f"[1/4] Creating worktree at {base_commit[:8]}...")
exec_command(
f"git worktree add -b {branch_name} {worktree_dir} {base_commit}",
cwd=repo_root,
)

print("[2/4] Running transformation...")
transform(Path(worktree_dir))

print("[3/4] Running pre-commit...")
exec_command("pre-commit run --all-files", cwd=worktree_dir, check=False)
if exec_command("git status --porcelain", cwd=worktree_dir):
git_add_and_commit("pre-commit fixes", cwd=worktree_dir)

print(f"[4/4] Diffing against {target_commit[:8]}...")
diff = exec_command(
f"git diff {target_commit} -- .",
cwd=worktree_dir,
check=False,
)

if diff:
print(f"\nFAIL: diff is non-empty:\n{diff}")
sys.exit(1)
else:
print("\nPASS: transform reproduces the commit exactly.")

finally:
print(f"\nWorktree left at: {worktree_dir}")
print(f"Branch: {branch_name}")
print("To clean up manually:")
print(f" git worktree remove {worktree_dir} && git branch -D {branch_name}")
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,3 @@ glm/
_examples_synced/
.env
.DS_Store
.claude/
Loading