89 lines
3.1 KiB
Python
89 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Scan ~/.hermes/skills/ for corrupted .py scripts.
|
|
|
|
Usage: python corruption-scanner.py [--fix-dir /path/to/output]
|
|
Output: JSON summary of clean vs corrupted files.
|
|
"""
|
|
import json, os, sys
|
|
from pathlib import Path
|
|
|
|
def scan_skills(base_dir):
|
|
results = {"clean": [], "corrupted": [], "skipped": []}
|
|
|
|
for root, dirs, files in os.walk(base_dir):
|
|
if '__pycache__' in root or 'venv' in root:
|
|
continue
|
|
|
|
for fname in files:
|
|
if not fname.endswith('.py'):
|
|
continue
|
|
|
|
fpath = os.path.join(root, fname)
|
|
size = os.path.getsize(fpath)
|
|
|
|
# Skip empty __init__.py (normal)
|
|
if fname == '__init__.py' and size <= 50:
|
|
results["skipped"].append({"path": fpath, "reason": "empty __init__.py"})
|
|
continue
|
|
|
|
try:
|
|
with open(fpath, 'r') as f:
|
|
content = f.read(1000)
|
|
|
|
first_line = content.strip().split('\n')[0].lower()
|
|
|
|
if '% partial rewrite' in first_line[:200] or 'latex' in first_line[:200]:
|
|
results["corrupted"].append({
|
|
"path": fpath,
|
|
"size": size,
|
|
"type": "latex_contamination"
|
|
})
|
|
elif first_line.startswith('%pdf') or '%PDF' in first_line[:20]:
|
|
results["corrupted"].append({
|
|
"path": fpath,
|
|
"size": size,
|
|
"type": "pdf_binary"
|
|
})
|
|
elif len(content) > 200000:
|
|
results["corrupted"].append({
|
|
"path": fpath,
|
|
"size": size,
|
|
"type": "oversized"
|
|
})
|
|
else:
|
|
results["clean"].append({"path": fpath, "size": size})
|
|
|
|
except UnicodeDecodeError:
|
|
results["skipped"].append({"path": fpath, "reason": "binary file"})
|
|
except Exception as e:
|
|
results["skipped"].append({"path": fpath, "reason": str(e)})
|
|
|
|
return results
|
|
|
|
if __name__ == '__main__':
|
|
base = os.environ.get('HERMES_HOME', str(Path.home() / '.hermes'))
|
|
skills_dir = os.path.join(base, 'skills')
|
|
|
|
fix_dir = None
|
|
args = sys.argv[1:]
|
|
if '--fix-dir' in args:
|
|
idx = args.index('--fix-dir')
|
|
if idx + 1 < len(args):
|
|
fix_dir = args[idx + 1]
|
|
|
|
results = scan_skills(skills_dir)
|
|
|
|
print(json.dumps(results, indent=2, ensure_ascii=False))
|
|
|
|
# Summary
|
|
print(f"\n{'='*60}")
|
|
print(f"Scan complete:")
|
|
print(f" Clean: {len(results['clean'])}")
|
|
print(f" Corrupted: {len(results['corrupted'])}")
|
|
print(f" Skipped: {len(results['skipped'])}")
|
|
|
|
if results['corrupted']:
|
|
print(f"\nCorrupted files:")
|
|
for f in results['corrupted']:
|
|
print(f" ❌ {f['path']} ({f['size']:,} bytes) - {f['type']}")
|