debug_residue.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """PostToolUse hook (GLOBAL): 写源码后扫描调试残留。
  4. 对齐 Rules §10(错误闭环/勿留调试):捕获 var_dump/print_r/var_export/die()/exit()/console.log。
  5. 仅对文本源文件生效,跳过 tests 目录(测试辅助允许)。非阻断 exit 1 回显 AI。
  6. """
  7. import sys
  8. import os
  9. import json
  10. import re
  11. TEXT_EXT = {".php", ".html", ".htm", ".js", ".css", ".py", ".json", ".md", ".txt"}
  12. DEBUG = re.compile(
  13. r"(?:var_dump|print_r|var_export|\bdie\b|(?<!\.)\bexit\b|console\s*\.\s*log)\s*\("
  14. )
  15. def main():
  16. try:
  17. raw = sys.stdin.read()
  18. if not raw.strip():
  19. return 0
  20. data = json.loads(raw)
  21. except Exception:
  22. return 0
  23. tool_input = data.get("tool_input", {}) or {}
  24. path = (
  25. tool_input.get("filePath")
  26. or tool_input.get("file_path")
  27. or tool_input.get("path")
  28. or ""
  29. )
  30. if not path:
  31. return 0
  32. path = os.path.abspath(path)
  33. if os.path.splitext(path)[1].lower() not in TEXT_EXT:
  34. return 0
  35. # 跳过测试目录,避免误报测试辅助代码
  36. if any(s.lower() in ("tests", "test") for s in path.split(os.sep)):
  37. return 0
  38. if not os.path.isfile(path):
  39. return 0
  40. try:
  41. with open(path, "r", encoding="utf-8", errors="ignore") as f:
  42. text = f.read()
  43. except Exception:
  44. return 0
  45. hits = []
  46. for m in DEBUG.finditer(text):
  47. line = text.count("\n", 0, m.start()) + 1
  48. hits.append((line, m.group(0).strip()))
  49. if hits:
  50. print("[DEBUG-WARN] 发现调试残留,请确认是否应保留(Rules §10):")
  51. for line, tok in hits:
  52. print(" 行 %d: %s" % (line, tok))
  53. return 1
  54. return 0
  55. if __name__ == "__main__":
  56. sys.exit(main())