The gate now runs pytest as well, so one command answers whether the code base is broken: syntax, protocol imports, the 125 core tests, then the lab functional suites. It fails when a test fails, verified by feeding it a deliberately broken test. Two leftovers from moving the labs into experiments/ are fixed: the lab command still pointed at tests/, and the hook only watched protocol and tests, so edits under experiments/ and tools/ triggered nothing. Profiling the 3.6 s gate: 0.24 s syntax, 0.12 s imports, 0.61 s pytest, 2.7 s lab functional suites, of which Lab042's software loopback is 1.14 s because it pushes a whole image through the chain. The pytest addition is the small part. prepare_jpeg is now cached, since six checks call it and each call re-encoded the image at several qualities. README described the gate without the tests it now runs.
60 lines
1.7 KiB
Python
60 lines
1.7 KiB
Python
"""
|
||
Обёртка быстрого шлюза для хука PostToolUse.
|
||
|
||
Читает JSON события со стандартного ввода. Если правка затронула файл Python
|
||
в protocol или tests, запускает tools/quick_gate.py.
|
||
|
||
Коды возврата:
|
||
0 — правка не по теме либо шлюз пройден, вывода нет;
|
||
2 — шлюз не пройден, текст ошибки уходит в stderr и возвращается модели.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import os
|
||
from pathlib import Path
|
||
import re
|
||
import subprocess
|
||
import sys
|
||
|
||
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
||
WATCHED = re.compile(r"[\\/](?:protocol|experiments|tests|tools)[\\/][^\\/]+\.py$")
|
||
|
||
|
||
def main() -> int:
|
||
try:
|
||
event = json.load(sys.stdin)
|
||
except (json.JSONDecodeError, ValueError):
|
||
return 0
|
||
|
||
tool_input = event.get("tool_input") or {}
|
||
tool_response = event.get("tool_response") or {}
|
||
file_path = tool_response.get("filePath") or tool_input.get("file_path") or ""
|
||
|
||
if not WATCHED.search(str(file_path)):
|
||
return 0
|
||
|
||
environment = dict(os.environ, PYTHONIOENCODING="utf-8")
|
||
|
||
completed = subprocess.run(
|
||
[sys.executable, str(PROJECT_ROOT / "tools" / "quick_gate.py")],
|
||
cwd=PROJECT_ROOT,
|
||
capture_output=True,
|
||
text=True,
|
||
encoding="utf-8",
|
||
errors="replace",
|
||
env=environment,
|
||
)
|
||
|
||
if completed.returncode == 0:
|
||
return 0
|
||
|
||
output = (completed.stdout + completed.stderr).strip()
|
||
print(output, file=sys.stderr)
|
||
return 2
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main())
|