---
name: agent_launch_worktree
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func AgentLaunchWorktree(cfg WorktreeLaunchConfig) WorktreeLaunchResult"
description: "Crea un git worktree nuevo en una rama derivada de master y lanza `claude -p <prompt>` headless dentro de ese worktree, redirigiendo stdout+stderr a un log file. Devuelve inmediatamente con el PID — el proceso queda corriendo en background. Si `ResetIfExists=true` y la rama existe, borra rama + worktree previos (best-effort) antes de recrear. Si `claude` no esta en PATH, hace fallback a `echo` como stub para que los tests puedan correr sin el binario real. Usa exec.LookPath, NO hardcodea paths. Cleanup del worktree + branch se hace con `agent_cleanup_worktree_go_infra`."
tags: [agents, worktree, claude, git, headless]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: ["fmt", "os", "os/exec", "strings", "time"]
params:
  - name: cfg
    desc: "WorktreeLaunchConfig con RepoRoot (path absoluto al repo principal), Branch (ej. auto/0115-foo), WorktreePath (path absoluto donde crear el worktree), Prompt (texto pasado a claude -p), LogPath (archivo de log), Env opcional (env vars extra), SkipPerms (pasa --dangerously-skip-permissions), ResetIfExists (nuke previo de rama+worktree)."
output: "WorktreeLaunchResult con PID (claude process id), Branch/WorktreePath/LogPath (eco de inputs), StartedAt (unix seconds) y Error (string vacio en exito; mensaje en fallo). PID=0 cuando Error!='' . El campo Error usa string en vez de error nativo Go para poder serializarse a JSON desde agent_runner_api."
tested: true
tests:
  - "creates worktree dir and branch off master"
  - "ResetIfExists=true on existing branch+worktree succeeds"
  - "returns Error when RepoRoot/Branch/WorktreePath missing"
test_file_path: "functions/infra/agent_launch_worktree_test.go"
file_path: "functions/infra/agent_launch_worktree.go"
---

## Ejemplo

```go
res := infra.AgentLaunchWorktree(infra.WorktreeLaunchConfig{
    RepoRoot:      "$HOME/fn_registry",
    Branch:        "auto/0115-worktree-launcher-fn",
    WorktreePath:  "$HOME/fn_registry/worktrees/0115-worktree-launcher-fn",
    Prompt:        "Implement issue 0115 — worktree launcher Go function",
    LogPath:       "/tmp/claude-0115.log",
    SkipPerms:     true,
    ResetIfExists: true,
})
if res.Error != "" {
    log.Fatal(res.Error)
}
fmt.Printf("claude PID=%d branch=%s log=%s\n", res.PID, res.Branch, res.LogPath)
// ... agente trabaja ...
infra.AgentCleanupWorktree(res.WorktreePath, res.Branch, "$HOME/fn_registry", res.PID)
```

## Cuando usarla

Cuando una app (`agent_runner_api`, `fn-orquestador`) o un script necesite lanzar Claude headless en un sandbox aislado: ramas `auto/<issue>` o `issue/<NNNN>`. Reemplaza el bash inline que vivia en `.claude/skills/parallel-fix-issues/` y en el agente `fn-orquestador`. Si lo que quieres es ejecutar Claude en foreground sin worktree, NO uses esta — usa un `exec.Command` directo.

## Gotchas

- **Spawn solo, no Wait**: la funcion hace `cmd.Start()` y vuelve. Si el caller necesita esperar al final, debe trackear el PID y hacer `syscall.Wait4` o consultar `/proc/<pid>`. Para cleanup ordenado, usa `agent_cleanup_worktree_go_infra`.
- **Master debe existir** en `RepoRoot` — la rama se crea con `git worktree add ... -b <branch> master`. Si tu repo usa `main`, fork la funcion o renombra la rama localmente.
- **`ResetIfExists` es best-effort**: si el worktree previo tiene cambios sin commitear o procesos atados, `git worktree remove --force` puede ignorar ciertos errores; siempre revisa el dir final.
- **Log file truncado**: cada launch reabre `LogPath` con `O_TRUNC`. Si quieres preservar el log de runs anteriores, rota el archivo antes de llamar.
- **Fallback `echo` stub** se activa cuando `exec.LookPath("claude")` falla; en ese caso el "proceso claude" imprime `STUB: claude not in PATH, prompt was: <prompt>` y termina inmediatamente. Util en CI/tests, no en produccion.
- **PID en Windows**: `syscall.Kill` no existe en Windows — `agent_cleanup_worktree` solo funciona en Linux/Darwin. Documentado alli.
- **Env**: los valores de `cfg.Env` se hacen append a `os.Environ()` — si quieres anular una var existente, en Go la ultima asignacion gana, asi que basta con incluirla en `cfg.Env`.
