From idm-skills
Use this skill when applying fixes to Python 3 code review findings from REVIEW.md. Covers reading source files, applying intelligent fixes, committing each fix atomically, and producing a REVIEW-FIX.md report. Python 3 only — do NOT use for other languages, initial code review, test running, or deployment tasks.
How this skill is triggered — by the user, by Claude, or both
Slash command
/idm-skills:python-code-fixerThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Applies fixes to Python 3 code review findings from `REVIEW.md`. Produces a `REVIEW-FIX.md` artifact next to the source review file.
Applies fixes to Python 3 code review findings from REVIEW.md. Produces a REVIEW-FIX.md artifact next to the source review file.
Usage: Load this skill in Claude Code to apply fixes to Python 3 code review findings from REVIEW.md.
This skill runs in one of two modes:
./REVIEW.md from the project root (matching the output of the companion python-code-reviewer skill), writes ./REVIEW-FIX.md, edits files in the current working tree, and does not create a worktree. Skip Step 1 entirely.<config> block with phase_dir, padded_phase, review_path, fix_report_path. Runs the full worktree-based flow in Step 1.Detect the mode in Step 2 by checking whether a <config> block is present in the prompt.
Scope: Python 3 source files (
.py) only. Skip any finding that targets a non-Python file and mark it as "skipped: non-Python file, out of scope".
Job: Read REVIEW.md findings → fix source code intelligently (not blindly) → commit each fix atomically → produce REVIEW-FIX.md report.
CRITICAL — Mandatory Initial Read: If the prompt contains a
<required_reading>block, use theReadtool to load every file listed there before any other action. This is primary context.
Before fixing code, discover project context:
Project instructions: Read ./CLAUDE.md if it exists. Follow all project-specific guidelines, security requirements, and coding conventions.
Project skills: Check .claude/skills/ or .agents/skills/ if either exists:
SKILL.md for each skill (lightweight index ~130 lines)rules/*.md files as neededAGENTS.md files (100KB+ context cost)The REVIEW.md fix suggestion is guidance, not a patch to apply blindly.
For each finding:
If the source file has changed significantly and the fix no longer applies cleanly:
If multiple files are referenced in the Fix section:
Before editing any file for a finding, establish safe rollback capability.
Protocol:
touched_files before editing anything.git checkout -- {file} for EACH file in touched_files.git checkout -- reverts only the uncommitted in-progress change and does not affect commits from prior findings.Rollback scope: Per-finding only. Files modified by prior (already committed) findings are NOT touched during rollback.
After applying each fix, verify correctness in 3 tiers.
Run the Python 3 syntax check on the modified .py file. Try python3 first, then python (Windows typically only ships python):
POSIX shells:
PY=$(command -v python3 || command -v python)
"$PY" -m py_compile {file} && echo "OK"
PowerShell:
$py = (Get-Command python3 -ErrorAction SilentlyContinue) ?? (Get-Command python -ErrorAction SilentlyContinue)
if ($py) { & $py.Source -m py_compile {file}; if ($LASTEXITCODE -eq 0) { "OK" } }
Scoping rules:
python3 nor python is available: fall back to Tier 3 — do NOT rollback.If no Python interpreter is on PATH (e.g., restricted environment):
Logic bug limitation: Tier 1 and Tier 2 verify syntax/structure only, NOT semantic correctness. For findings where REVIEW.md classifies the issue as a logic error (incorrect condition, wrong algorithm, bad state handling), set the commit status in REVIEW-FIX.md as "fixed: requires human verification" rather than "fixed".
Each finding starts with:
### {ID}: {Title}
ID matches: CR-\d+ or BL-\d+ (Critical), WR-\d+ (Warning), or IN-\d+ (Info)
path/to/file.ext:42 or path/to/file.ext**Fix:** to next ### heading or end of fileThe Fix: section may contain:
Inline code or code fences:
```language
code snippet
```
Extract code from triple-backtick fences.
IMPORTANT: Code fences may contain markdown-like syntax (headings, horizontal rules). Always track fence open/close state when scanning for section boundaries. Content between ``` delimiters is opaque — never parse it as finding structure.
Multiple file references:
"In module_a.py, change X; in module_b.py, change Y" — parse ALL file references into the finding's files array.
Prose-only descriptions: "Add null check before accessing property" — interpret intent and apply fix.
### heading or --- footer### boundaries, treat content inside triple-backtick fences as opaque — do NOT match ### or --- inside fenced blocks### headings inside a code fence (e.g., example markdown output) are NOT finding boundariesStandalone Mode: Skip this entire step. Operate on the current working tree, in the current branch. Proceed directly to Step 2.
Phase Mode only: When invoked by an orchestrator with a
<config>block, create a dedicated git worktree BEFORE touching any files.
This skill, when run in Phase Mode, runs as a background process that makes commits. Operating on the main working tree would race the foreground session. Every Phase-Mode instance runs in its own isolated worktree.
The bash block below is POSIX-only (uses
mktemp,awk,sed,node). It is intended for the orchestrator's Linux/macOS environment. Do not attempt to translate it to PowerShell for direct user runs — Standalone Mode skips this step entirely.
The cleanup tail (commit fixes → remove worktree → drop recovery sentinel) MUST be transactional. If the process is interrupted between the last commit and git worktree remove, a discoverable recovery sentinel must be left behind for future cleanup.
branch=$(git branch --show-current)
test -n "$branch" || { echo "Detached HEAD is not supported for review-fix (#2686)"; exit 1; }
# Recovery-sentinel handling (#2839):
sentinel="${phase_dir}/.review-fix-recovery-pending.json"
if [ -f "$sentinel" ]; then
echo "Detected pre-existing recovery sentinel from a prior interrupted run: $sentinel"
prior_recovery=$(node -e '
const fs = require("fs");
try {
const parsed = JSON.parse(fs.readFileSync(process.argv[1], "utf-8"));
process.stdout.write((parsed.worktree_path || "") + "\n" + (parsed.reviewfix_branch || ""));
} catch (err) {
process.stderr.write(`Warning: malformed recovery sentinel ${process.argv[1]}: ${err.message}\n`);
process.stdout.write("\n");
}
' "$sentinel")
prior_wt="$(printf '%s' "$prior_recovery" | sed -n '1p')"
prior_branch="$(printf '%s' "$prior_recovery" | sed -n '2p')"
if [ -n "$prior_wt" ] && git worktree list --porcelain | grep -q "^worktree $prior_wt$"; then
echo "Removing orphan worktree from prior run: $prior_wt"
git worktree remove "$prior_wt" --force || true
fi
if [ -n "$prior_branch" ]; then
echo "Removing orphan reviewfix branch from prior run: $prior_branch"
git branch -D "$prior_branch" 2>/dev/null || true
fi
rm -f "$sentinel"
fi
wt=$(mktemp -d "/tmp/sv-${padded_phase}-reviewfix-XXXXXX")
reviewfix_branch="python-reviewfix/${padded_phase}-$$"
git worktree add -b "$reviewfix_branch" "$wt" "$branch"
# Write recovery sentinel ONLY AFTER `git worktree add` succeeds
node -e '
const fs = require("fs");
const [sentinelPath, worktree_path, branch, reviewfix_branch, padded_phase] = process.argv.slice(1);
fs.writeFileSync(sentinelPath, JSON.stringify({
worktree_path,
branch,
reviewfix_branch,
padded_phase,
started_at: new Date().toISOString()
}, null, 2));
' "$sentinel" "$wt" "$branch" "$reviewfix_branch" "$padded_phase"
cd "$wt"
Concrete steps:
padded_phase and phase_dir from the <config> block.branch=$(git branch --show-current). If empty (detached HEAD), print error and exit.${phase_dir}/.review-fix-recovery-pending.json exists, parse it, attempt to remove the orphan worktree (best-effort, --force), delete the stale reviewfix_branch (best-effort, git branch -D), then delete the stale sentinel.wt=$(mktemp -d "/tmp/sv-${padded_phase}-reviewfix-XXXXXX").git worktree add -b "$reviewfix_branch" "$wt" "$branch" — attaches to a NEW branch so it coexists with the user's checkout (#2990).${phase_dir}/.review-fix-recovery-pending.json containing {worktree_path, branch, reviewfix_branch, padded_phase, started_at}. Only write AFTER git worktree add succeeds.$wt.If git worktree add fails: surface the error and exit. Do not force-remove the path. Do not write the sentinel.
Cleanup tail (transactional — ALWAYS, even on failure):
# Step 1: fast-forward $branch to capture agent commits
main_repo="$(git worktree list --porcelain | awk '/^worktree / { sub(/^worktree /, ""); print; exit }')"
ff_status=0
if git -C "$main_repo" merge --ff-only "$reviewfix_branch" 2>&1; then
ff_status=0
else
ff_status=$?
echo "WARN: could not fast-forward $branch to $reviewfix_branch (exit $ff_status)."
echo " The temp branch $reviewfix_branch is preserved for manual merge."
fi
# Step 2: drop the worktree
git worktree remove "$wt" --force
# Step 3: delete temp branch ONLY if fast-forward succeeded
if [ "$ff_status" -eq 0 ]; then
git -C "$main_repo" branch -D "$reviewfix_branch" || true
fi
# Step 4: drop the recovery sentinel ONLY after worktree remove succeeds
rm -f "$sentinel"
Read mandatory files: Load all files from <required_reading> block if present.
Detect mode and resolve config:
If a <config> block is present in the prompt → Phase Mode. Extract:
phase_dir: e.g., .planning/phases/02-code-review-commandpadded_phase: e.g., "02"review_path: e.g., .planning/phases/02-code-review-command/02-REVIEW.mdfix_scope: "critical_warning" (default) or "all" (includes Info findings)fix_report_path: e.g., .planning/phases/02-code-review-command/02-REVIEW-FIX.mdOtherwise → Standalone Mode. Use these defaults (no <config> required):
review_path = ./REVIEW.md (matches output of the python-code-reviewer skill)fix_report_path = ./REVIEW-FIX.mdfix_scope = "critical_warning"phase_dir and padded_phase are not used in Standalone Mode.Read REVIEW.md: Use the Read tool on {review_path} (do not shell out to cat — it is not cross-platform).
Parse frontmatter status field: If status is "clean" or "skipped", exit with message: "No issues to fix — REVIEW.md status is {status}." Do NOT create REVIEW-FIX.md. Exit code 0.
Load project context: Read ./CLAUDE.md and check for .claude/skills/ or .agents/skills/.
Extract findings from REVIEW.md body using the finding parser rules above.
For each finding, extract:
id: e.g., CR-01, WR-03, IN-12severity: Critical (CR-* or BL-), Warning (WR-), Info (IN-*)title: from ### headingfile: primary file path from File: linefiles: ALL file paths referenced in finding (including Fix section)line: line number if present, else nullissue: from Issue: linefix: full fix content from Fix: sectionFilter by fix_scope:
"critical_warning": include CR-, BL-, WR-* only"all": include CR-, BL-, WR-, IN-Sort by severity: Critical first, then Warning, then Info. Within same severity, maintain document order.
Record findings_in_scope for REVIEW-FIX.md frontmatter.
For each finding in sorted order:
a. Read source files
b. Record files to touch
touched_files before editing anythingc. Determine if fix applies
d. Apply fix or skip
If fix applies cleanly:
If code context differs significantly:
e. Verify fix (3-tier strategy above)
f. Commit fix atomically
Examples:
fix(02): CR-01 fix SQL injection in auth.pyfix(03): WR-05 add None check before list access in utils.pyMultiple files: list ALL modified files after the message (space-separated).
Extract commit hash:
COMMIT_HASH=$(git rev-parse --short HEAD)
If commit FAILS after successful edit:
g. Record result
{
"finding_id": "CR-01",
"status": "fixed" | "skipped",
"files_modified": ["path/to/file1.py", "path/to/file2.py"], # if fixed
"commit_hash": "abc1234", # if fixed
"skip_reason": "code context differs from review" # if skipped
}
h. Safe arithmetic for counters
FIXED_COUNT=$((FIXED_COUNT + 1)) # correct
# ((FIXED_COUNT++)) # WRONG — fails under set -e
Create REVIEW-FIX.md at fix_report_path.
YAML frontmatter:
---
phase: {phase}
fixed_at: {ISO timestamp}
review_path: {path to source REVIEW.md}
iteration: {current iteration number, default 1}
findings_in_scope: {count}
fixed: {count}
skipped: {count}
status: all_fixed | partial | none_fixed
---
Status values:
all_fixed: All in-scope findings successfully fixedpartial: Some fixed, some skippednone_fixed: All findings skippedBody structure:
# Phase {X}: Code Review Fix Report
**Fixed at:** {timestamp}
**Source review:** {review_path}
**Iteration:** {N}
**Summary:**
- Findings in scope: {count}
- Fixed: {count}
- Skipped: {count}
## Fixed Issues
{If none, write: "None — all findings were skipped."}
### {finding_id}: {title}
**Files modified:** `file1`, `file2`
**Commit:** {hash}
**Applied fix:** {brief description of what was changed}
## Skipped Issues
{Omit section if none}
### {finding_id}: {title}
**File:** `path/to/file.ext:{line}`
**Reason:** {skip_reason}
**Original issue:** {issue description from REVIEW.md}
---
_Fixed: {timestamp}_
_Fixer: Claude (python-code-fixer)_
_Iteration: {N}_
DO NOT commit REVIEW-FIX.md — the orchestrator handles that commit. This skill only commits individual per-finding fix changes.
git worktree add -b "$reviewfix_branch" "$wt" "$branch". Using mktemp ensures concurrent runs don't collide. Commits advance $reviewfix_branch; the cleanup tail fast-forwards $branch to capture them. Standalone Mode operates on the current working tree and does not create a worktree.merge --ff-only, (2) worktree remove, (3) branch -D (only if ff succeeded), (4) rm -f "$sentinel". Never reorder. Does not apply in Standalone Mode.Bash(cat << 'EOF'), heredocs, or node -e 'fs.writeFileSync(...)' to materialize files. (The Phase-Mode sentinel write is the one orchestrator-internal exception; user-visible artifacts always go through the Write tool.)git checkout -- {file} — atomic and safe. Do NOT use Write tool for rollback.Fixes are committed per-finding. Implications:
git log."fix({padded_phase}): {id} {description} formatgit checkout)git checkout -- {file} (not Write tool)Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub shchen-idmod/company-skills --plugin idm-skills