from __future__ import annotations import re import subprocess from pathlib import Path from typing import Any from uuid import uuid4 from app.agents.isolation.strategy_selector import IsolationDecision class WorktreeIsolationError(RuntimeError): pass def _slugify(value: str, *, fallback: str) -> str: slug = re.sub(r"[^a-zA-Z0-9._-]+", "-", (value or "").strip()).strip("-").lower() return slug or fallback def _resolve_git_root() -> Path: try: result = subprocess.run( ["git", "rev-parse", "--show-toplevel"], check=True, capture_output=True, text=True, ) except subprocess.CalledProcessError as exc: raise WorktreeIsolationError(exc.stderr.strip() or exc.stdout.strip() or "git_root_unavailable") from exc git_root = Path(result.stdout.strip()) if not git_root.exists(): raise WorktreeIsolationError("git_root_not_found") return git_root def prepare_worktree_isolation( *, state: dict[str, Any], decision: IsolationDecision, role_value: str, sub_commander: str, create_workspace: bool = True, ) -> dict[str, Any]: isolation_id = f"worktree-{uuid4().hex[:8]}" conversation_slug = _slugify(str(state.get("conversation_id") or "conversation"), fallback="conversation") role_slug = _slugify(role_value, fallback="agent") git_root = _resolve_git_root() workspace_root = git_root / ".worktrees" / "jarvis" / conversation_slug workspace_path = workspace_root / f"{role_slug}-{isolation_id}" branch = f"jarvis/{conversation_slug}/{role_slug}-{isolation_id}" if create_workspace and not workspace_path.exists(): workspace_root.mkdir(parents=True, exist_ok=True) try: subprocess.run( ["git", "-C", str(git_root), "worktree", "add", "-b", branch, str(workspace_path), "HEAD"], check=True, capture_output=True, text=True, ) except subprocess.CalledProcessError as exc: raise WorktreeIsolationError(exc.stderr.strip() or exc.stdout.strip() or "worktree_add_failed") from exc return { "mode": "worktree", "isolation_id": isolation_id, "workspace_path": str(workspace_path), "parent_conversation_id": str(state.get("conversation_id") or "") or None, "metadata": { **dict(decision.metadata or {}), "reason": decision.reason, "role": role_value, "sub_commander": sub_commander, "tool_names": list(decision.tool_names), "capability_ids": list(decision.capability_ids), "repo_root": str(git_root), "branch": branch, "workspace_strategy": "ephemeral_worktree", "cleanup_status": "pending", "materialized": workspace_path.exists(), }, }