Merge pull request #524 from AIOSAI/work/system-fix-pr-stacking-and-diagnostics-double-fire
feat(system): fix PR stacking and diagnostics double-fire
This commit is contained in:
@@ -299,9 +299,30 @@ def is_same_file_as_last(file_path: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _project_has_own_posttooluse_hooks() -> bool:
|
||||
"""Check if CWD is inside a project with its own PostToolUse hooks."""
|
||||
search = Path.cwd()
|
||||
home = Path.home()
|
||||
while search != home and search.parent != search:
|
||||
settings = search / ".claude" / "settings.json"
|
||||
if settings.exists():
|
||||
try:
|
||||
data = json.loads(settings.read_text(encoding="utf-8"))
|
||||
ptu = data.get("hooks", {}).get("PostToolUse", [])
|
||||
if ptu:
|
||||
return True
|
||||
except (json.JSONDecodeError, OSError):
|
||||
pass
|
||||
search = search.parent
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""Main hook entry point."""
|
||||
try:
|
||||
if _project_has_own_posttooluse_hooks():
|
||||
return
|
||||
|
||||
input_data = json.load(sys.stdin)
|
||||
tool_name = input_data.get("tool_name", "")
|
||||
tool_input = input_data.get("tool_input", {})
|
||||
@@ -318,10 +339,8 @@ def main():
|
||||
|
||||
# Collect all errors
|
||||
errors = []
|
||||
file_type = ""
|
||||
|
||||
if file_path.endswith(".py"):
|
||||
file_type = "Python"
|
||||
errors = run_python_checks(file_path)
|
||||
|
||||
# Seedgo standards checklist
|
||||
@@ -339,7 +358,6 @@ def main():
|
||||
save_diagnostics_state(file_path, ruff_lint_errors + type_errors)
|
||||
|
||||
elif file_path.endswith(".json"):
|
||||
file_type = "JSON"
|
||||
errors = run_json_checks(file_path)
|
||||
else:
|
||||
return
|
||||
|
||||
@@ -17,6 +17,7 @@ and cleanup (checkout main + release lock) in a finally block.
|
||||
from __future__ import annotations
|
||||
|
||||
import json as _json
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
@@ -73,18 +74,26 @@ To contribute from a fork:
|
||||
"""
|
||||
|
||||
|
||||
def _resolve_git_branch(branch_name: str, branch_dir: Path) -> str:
|
||||
"""Read git_branch from passport if available, else fall back to citizen/{name}."""
|
||||
def _slugify(description: str) -> str:
|
||||
"""Convert description to a branch-safe slug."""
|
||||
slug = description.lower().strip().replace(" ", "-")
|
||||
slug = re.sub(r"[^a-z0-9-]", "", slug)
|
||||
slug = re.sub(r"-{2,}", "-", slug).strip("-")
|
||||
return slug[:50]
|
||||
|
||||
|
||||
def _resolve_git_branch(branch_name: str, branch_dir: Path, slug: str = "") -> str:
|
||||
"""Read git_branch from passport as prefix, append slug for uniqueness."""
|
||||
passport_path = branch_dir / ".trinity" / "passport.json"
|
||||
if passport_path.is_file():
|
||||
try:
|
||||
data = _json.loads(passport_path.read_text())
|
||||
git_branch = data.get("branch_info", {}).get("git_branch", "")
|
||||
if git_branch:
|
||||
return git_branch
|
||||
return f"{git_branch}-{slug}" if slug else git_branch
|
||||
except (ValueError, OSError) as exc:
|
||||
logger.warning("Failed to read git_branch from passport %s: %s", passport_path, exc)
|
||||
return f"citizen/{branch_name}"
|
||||
return f"citizen/{branch_name}-{slug}" if slug else f"citizen/{branch_name}"
|
||||
|
||||
|
||||
def create_pr(branch_name: str, description: str, branch_dir: Path) -> dict:
|
||||
@@ -115,7 +124,8 @@ def create_pr(branch_name: str, description: str, branch_dir: Path) -> dict:
|
||||
Dict with success, pr_url, feature_branch, and message.
|
||||
"""
|
||||
repo_root = find_repo_root()
|
||||
feature_branch = _resolve_git_branch(branch_name, branch_dir)
|
||||
slug = _slugify(description)
|
||||
feature_branch = _resolve_git_branch(branch_name, branch_dir, slug)
|
||||
lock_acquired = False
|
||||
|
||||
result = {
|
||||
@@ -209,9 +219,9 @@ def create_pr(branch_name: str, description: str, branch_dir: Path) -> dict:
|
||||
logger.error(result["message"])
|
||||
return result
|
||||
|
||||
# Step 7: Push feature branch (force-with-lease for persistent citizen branches)
|
||||
# Step 7: Push feature branch
|
||||
push = subprocess.run(
|
||||
["git", "push", "--force-with-lease", "origin", feature_branch],
|
||||
["git", "push", "-u", "origin", feature_branch],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=str(repo_root),
|
||||
@@ -244,7 +254,7 @@ def create_pr(branch_name: str, description: str, branch_dir: Path) -> dict:
|
||||
cwd=str(repo_root),
|
||||
)
|
||||
if pr_create.returncode != 0:
|
||||
# Check if PR already exists — force-push already updated it
|
||||
# Check if PR already exists for this branch
|
||||
existing = subprocess.run(
|
||||
["gh", "pr", "list", "--head", feature_branch, "--json", "url", "--limit", "1"],
|
||||
capture_output=True,
|
||||
@@ -258,7 +268,7 @@ def create_pr(branch_name: str, description: str, branch_dir: Path) -> dict:
|
||||
existing_prs = []
|
||||
if existing_prs:
|
||||
pr_url = existing_prs[0]["url"]
|
||||
logger.info("Existing PR updated via force-push: %s", pr_url)
|
||||
logger.info("Existing PR found: %s", pr_url)
|
||||
else:
|
||||
result["message"] = f"PR creation failed: {pr_create.stderr.strip()}"
|
||||
logger.error(result["message"])
|
||||
|
||||
@@ -92,8 +92,8 @@ def create_system_pr(description: str, caller: str) -> dict:
|
||||
"""
|
||||
repo_root = find_repo_root()
|
||||
slug = slugify(description)
|
||||
passport_branch = _resolve_system_git_branch(caller, repo_root)
|
||||
feature_branch = passport_branch if passport_branch else f"system/{caller}-{slug}"
|
||||
passport_prefix = _resolve_system_git_branch(caller, repo_root)
|
||||
feature_branch = f"{passport_prefix}-{slug}" if passport_prefix else f"system/{caller}-{slug}"
|
||||
lock_acquired = False
|
||||
|
||||
result: dict = {
|
||||
@@ -210,7 +210,7 @@ def create_system_pr(description: str, caller: str) -> dict:
|
||||
|
||||
# Step 7: Push feature branch
|
||||
push = subprocess.run(
|
||||
["git", "push", "--force-with-lease", "origin", feature_branch],
|
||||
["git", "push", "-u", "origin", feature_branch],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=str(repo_root),
|
||||
|
||||
Reference in New Issue
Block a user