Files
PDFToMD/.codex/hooks/handoff_policy.py
T
김경종 7e985ae94a add files
2026-04-30 17:05:19 +09:00

96 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""Require PLAN/PROGRESS handoff discipline for multi-agent work."""
from __future__ import annotations
import json
import subprocess
import sys
from pathlib import Path
TRACKED_PREFIXES = (
".agents/",
".codex/",
"AGENTS.md",
"PLAN.md",
"docs/",
"phases/",
"plugins/",
"requirements.txt",
"scripts/",
"src/",
"tests/",
)
def git_status_names(root: Path) -> list[str]:
result = subprocess.run(
["git", "status", "--porcelain"],
cwd=root,
capture_output=True,
text=True,
timeout=20,
)
if result.returncode != 0:
return []
names: list[str] = []
for line in result.stdout.splitlines():
if not line.strip():
continue
path = line[3:].replace("\\", "/")
if " -> " in path:
path = path.split(" -> ", 1)[1]
names.append(path)
return names
def is_coordination_relevant(path: str) -> bool:
return any(path == prefix or path.startswith(prefix) for prefix in TRACKED_PREFIXES)
def block(reason: str) -> int:
json.dump({"decision": "block", "reason": reason}, sys.stdout)
return 0
def main() -> int:
try:
payload = json.load(sys.stdin)
except json.JSONDecodeError:
return 0
if payload.get("stop_hook_active"):
return 0
root = Path(payload.get("cwd") or ".").resolve()
plan = root / "PLAN.md"
progress = root / "PROGRESS.md"
if not plan.exists() or not progress.exists():
return block(
"Multi-agent coordination requires PLAN.md and PROGRESS.md. "
"Create or restore both files before ending the turn."
)
changed = git_status_names(root)
if not changed:
return 0
relevant = [path for path in changed if is_coordination_relevant(path)]
progress_changed = "PROGRESS.md" in changed
if relevant and not progress_changed:
return block(
"Repository planning, docs, code, tests, requirements, or .codex files changed, "
"but PROGRESS.md was not updated. Add a concise handoff note so the next agent "
"can see what changed, what was verified, and what remains next."
)
return 0
if __name__ == "__main__":
raise SystemExit(main())