skills/code-ratchets/SKILL.md
Implement code quality ratchets to prevent proliferation of deprecated patterns. Use when (1) migrating away from legacy code patterns, (2) enforcing gradual codebase improvements, (3) preventing copy-paste proliferation of deprecated practices, or (4) setting up pre-commit hooks to count and limit specific code patterns. A ratchet fails if pattern count exceeds OR falls below expected—ensuring patterns never increase and prompting updates when they decrease.
npx skillsauth add ad-sdl/madsci code-ratchetsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
A ratchet is a pre-commit check that counts deprecated patterns in your codebase against a hard-coded expected count. It fails in two cases:
This automates the manual code review process of saying "don't do this, we've stopped doing this."
Define what to count. Patterns work best when they're:
Examples:
TODO: comments# type: ignore annotationsvar declarations (vs let/const)Any type annotationsunsafe_parse(, legacy_auth(from old_module importCreate scripts/ratchet.py (or .sh):
#!/usr/bin/env python3
"""
Code ratchet: prevents deprecated patterns from proliferating.
Fails if count > expected (proliferation) or count < expected (time to ratchet down).
"""
import subprocess
import sys
# ============================================================
# RATCHET CONFIGURATION - Edit counts here as patterns decrease
# ============================================================
RATCHETS = {
"TODO comments": {
"pattern": r"TODO:",
"expected": 47,
"glob": "**/*.py",
"reason": "Resolve TODOs before adding new ones",
},
"Type ignores": {
"pattern": r"# type: ignore",
"expected": 23,
"glob": "**/*.py",
"reason": "Fix type errors instead of ignoring them",
},
"Any types": {
"pattern": r": Any[,\)\]]",
"expected": 12,
"glob": "**/*.py",
"reason": "Use specific types instead of Any",
},
}
def count_pattern(pattern: str, glob: str) -> int:
"""Count pattern occurrences using grep."""
try:
result = subprocess.run(
["grep", "-r", "-E", "--include", glob, "-c", pattern, "."],
capture_output=True,
text=True,
)
# Sum counts from all files (grep -c outputs "filename:count" per file)
total = sum(
int(line.split(":")[-1])
for line in result.stdout.strip().split("\n")
if line and ":" in line
)
return total
except Exception:
return 0
def main() -> int:
failed = False
for name, config in RATCHETS.items():
actual = count_pattern(config["pattern"], config["glob"])
expected = config["expected"]
if actual > expected:
print(f"❌ RATCHET FAILED: {name}")
print(f" Expected ≤{expected}, found {actual} (+{actual - expected})")
print(f" Reason: {config['reason']}")
print(f" Pattern: {config['pattern']}")
print()
failed = True
elif actual < expected:
print(f"🎉 RATCHET DOWN: {name}")
print(f" Expected {expected}, found {actual} (-{expected - actual})")
print(f" Update expected count in ratchet.py: {expected} → {actual}")
print()
failed = True # Still fail to prompt the update
else:
print(f"✓ {name}: {actual}/{expected}")
return 1 if failed else 0
if __name__ == "__main__":
sys.exit(main())
Add to .pre-commit-config.yaml:
repos:
- repo: local
hooks:
- id: code-ratchets
name: Code Ratchets
entry: python scripts/ratchet.py
language: python
pass_filenames: false
always_run: true
Install hooks:
pip install pre-commit
pre-commit install
Run the script once to get current counts, then set those as expected values:
# Get current counts
grep -r -E "TODO:" --include="*.py" -c . | awk -F: '{sum+=$2} END {print sum}'
# Update RATCHETS dict with actual counts
When the ratchet fails with "too few":
For simpler setups, use scripts/ratchet.sh:
#!/bin/bash
set -e
check_ratchet() {
local name="$1"
local pattern="$2"
local expected="$3"
local glob="$4"
local reason="$5"
actual=$(grep -r -E "$pattern" --include="$glob" . 2>/dev/null | wc -l | tr -d ' ')
if [ "$actual" -gt "$expected" ]; then
echo "❌ RATCHET FAILED: $name"
echo " Expected ≤$expected, found $actual"
echo " Reason: $reason"
exit 1
elif [ "$actual" -lt "$expected" ]; then
echo "🎉 RATCHET DOWN: $name"
echo " Update expected: $expected → $actual"
exit 1
else
echo "✓ $name: $actual/$expected"
fi
}
# ============ RATCHET CONFIGURATION ============
check_ratchet "TODO comments" "TODO:" 47 "*.py" "Resolve TODOs first"
check_ratchet "Type ignores" "# type: ignore" 23 "*.py" "Fix type errors"
echo "All ratchets passed!"
Keep patterns simple: Basic grep/regex. Avoid complex AST analysis—fragility outweighs precision.
One ratchet per concern: Separate ratchets for separate issues. Easier to track progress.
Document the "why": Include reason field explaining why the pattern is deprecated.
Fail on decrease: Always require manual update of expected counts. This creates an audit trail of progress.
Escape hatch: For exceptional cases, consider allowing bypass via commit message:
# In ratchet.py, check for bypass
import os
if os.environ.get("RATCHET_BYPASS"):
print("⚠️ Ratchet bypassed via RATCHET_BYPASS env var")
sys.exit(0)
Usage: RATCHET_BYPASS=1 git commit -m "Emergency fix, ratchet bypass justified: ..."
Gradual rollout: Start with high counts and let them naturally decrease. Don't set expected=0 on day one.
| Pattern | Regex | Use Case |
|---------|-------|----------|
| TODO comments | TODO: | Track technical debt |
| Type ignores | # type: ignore | Enforce typing |
| Any types | : Any[,\)\]] | Specific types |
| Console logs | console\.log\( | Remove debug code |
| Legacy imports | from legacy_module | Track migrations |
| Deprecated calls | deprecated_func\( | API migrations |
| Broad exceptions | except: or except Exception: | Specific exceptions |
| Magic numbers | \b\d{3,}\b (tuned) | Named constants |
development
How to approach tests, types, lints, and coverage
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.