--- 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.