Layer advisory Cursor hooks and skills on the PI executor, shrink the test-report rule to the validation contract, and fix MCP relative paths.
57 lines
1.9 KiB
Python
57 lines
1.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Advisory beforeShellExecution: bare pi_subagents.py run / broad pkill."""
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
import _lib as lib # noqa: E402
|
|
|
|
HOOK = "guard-pi-shell"
|
|
|
|
|
|
def main() -> None:
|
|
raw = lib.read_stdin()
|
|
lib.maybe_probe(raw, HOOK)
|
|
data = lib.parse_json_loose(raw)
|
|
if data is None:
|
|
lib.audit(HOOK, "UNRECOGNIZED_INPUT", reason="non_json_or_empty")
|
|
lib.allow()
|
|
|
|
cmd = lib.shell_command(data)
|
|
if not cmd:
|
|
lib.audit(HOOK, "UNRECOGNIZED_INPUT", reason="missing_command", keys=sorted(data.keys())[:40])
|
|
lib.allow()
|
|
|
|
compact = re.sub(r"\s+", " ", cmd).strip()
|
|
|
|
if re.search(r"(^|[;&|]\s*)pkill(\s|$)", compact) and re.search(r"\s-f(\s|$)", compact):
|
|
lib.audit(HOOK, "PKILL_ASK", command=compact[:500])
|
|
lib.ask(
|
|
"检测到 pkill -f(广谱杀进程)。AGENTS/PI 规则禁止广谱杀;请确认范围后再继续。",
|
|
"Hook requires confirmation for pkill -f.",
|
|
)
|
|
|
|
if re.search(r"pi_subagents\.py(\s|$)", compact) and re.search(r"(^|\s)run(\s|$)", compact):
|
|
has_lease = (
|
|
re.search(r"agentctl(\.py)?\s+with\b", compact) is not None
|
|
and re.search(r"--resource\s+path:", compact) is not None
|
|
)
|
|
if re.search(r"pi_subagents\.py\s+(roles|result|status|config)\b", compact):
|
|
lib.allow()
|
|
if not has_lease:
|
|
lib.audit(HOOK, "BARE_RUN_ASK", command=compact[:500])
|
|
lib.ask(
|
|
"裸调 pi_subagents.py run 缺少 agentctl with --resource path:… 租约。"
|
|
"报告路径须在 path:.doc/test-reports/assets/pi-subagents/<task>/<request> 租约内。",
|
|
"Hook: bare PI run without lease resource.",
|
|
)
|
|
|
|
lib.allow()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|