---
name: agent_cleanup_worktree
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func AgentCleanupWorktree(repoRoot, branch, worktreePath string, pid int) error"
description: "Tear-down de un worktree creado por agent_launch_worktree_go_infra: manda SIGTERM al PID (espera 1s, luego SIGKILL si sigue vivo), corre `git worktree remove --force` y `git branch -D` (best-effort cada uno). Devuelve error SOLO si los tres pasos fallan — fallos individuales son esperados (cleanup doble, rama ya borrada, etc.). PID=0 desactiva el kill (util cuando el proceso ya murio o nunca arranco). Linux/Darwin: usa syscall.Kill. Windows: la funcion compila pero el kill nunca hace nada porque syscall.Kill no existe alli — documentar como skip."
tags: [agents, worktree, cleanup, git, kill]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: ["fmt", "os/exec", "strings", "syscall", "time"]
params:
  - name: repoRoot
    desc: "path absoluto al repo principal (el que tiene el worktree registrado)."
  - name: branch
    desc: "nombre de la rama a borrar (ej. auto/0115-foo). Vacio = skip."
  - name: worktreePath
    desc: "path absoluto al worktree a eliminar. Vacio = skip."
  - name: pid
    desc: "PID de claude o 0 para saltarse el kill (proceso ya muerto / nunca arranco)."
output: "error nil cuando al menos uno de los tres pasos (kill, worktree remove, branch -D) tuvo exito o se salto. error no-nil solo si los tres fallaron — incluye los tres mensajes para diagnostico."
tested: true
tests:
  - "removes worktree dir and branch after launch"
  - "tolerates missing worktree/branch (cleanup called twice)"
test_file_path: "functions/infra/agent_cleanup_worktree_test.go"
file_path: "functions/infra/agent_cleanup_worktree.go"
---

## Ejemplo

```go
err := infra.AgentCleanupWorktree(
    "$HOME/fn_registry",
    "auto/0115-worktree-launcher-fn",
    "$HOME/fn_registry/worktrees/0115-worktree-launcher-fn",
    12345, // PID devuelto por AgentLaunchWorktree
)
if err != nil {
    log.Printf("cleanup partial failure: %v", err)
}
```

## Cuando usarla

Tras terminar (o abortar) un run lanzado con `agent_launch_worktree_go_infra`. Tambien util en defers de tests para garantizar limpieza: `defer infra.AgentCleanupWorktree(repo, branch, wt, res.PID)`. Si el run sigue corriendo y solo quieres parar el proceso sin tocar git, llama tu mismo a `syscall.Kill(pid, syscall.SIGTERM)` — esta funcion hace mas que eso.

## Gotchas

- **Best-effort por diseño**: cleanup doble no es error. Es deliberado para que `agent_runner_api` pueda llamarla en abort handlers sin meter el sistema en bucle.
- **SIGTERM grace 1s**: si claude tarda mas de 1s en cerrar limpiamente, se mata con SIGKILL — los buffers del log pueden quedar parcialmente escritos. Si necesitas mas grace, fork la funcion.
- **Windows**: `syscall.Kill` no existe en Windows. El codigo compila pero salta el kill silenciosamente. Para Windows real, swap `syscall.Kill` por `os.Process.Kill()` (requiere abrir el proceso primero con `os.FindProcess`).
- **Branch en HEAD del repo principal**: si la rama a borrar es la checked-out branch del repo principal, `git branch -D` falla — pero como worktree elimino ya su HEAD, en la practica nunca pasa con ramas `auto/*`.
- **Worktree con cambios sin commitear**: `--force` los descarta. Si necesitas preservar trabajo, commitea y push antes de llamar.
