Files
fn_registry/functions/infra/agent_launch_worktree.md
T
egutierrez a87c992cd9 feat(infra): agent_launch_worktree + agent_cleanup_worktree Go fns
Two Go functions in functions/infra/ for orchestrating headless Claude
agents inside isolated git worktrees:

- AgentLaunchWorktree(cfg): creates worktree off master, spawns
  claude -p in background, redirects stdout/stderr to LogPath. Falls
  back to echo stub when claude binary missing (CI/test friendly).
  ResetIfExists support for re-runs.

- AgentCleanupWorktree(repo, branch, path, pid): SIGTERM with 1s
  grace then SIGKILL, git worktree remove --force, git branch -D.
  Best-effort: only errors when all three steps fail (idempotent
  cleanup-twice).

Promotes inline bash from .claude/skills/parallel-fix-issues/ and
fn-orquestador to first-class registry functions. Closes issue 0115.

Capability group: agents.
2026-05-18 18:24:08 +02:00

4.3 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports params output tested tests test_file_path file_path
agent_launch_worktree function go infra 1.0.0 impure func AgentLaunchWorktree(cfg WorktreeLaunchConfig) WorktreeLaunchResult 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`.
agents
worktree
claude
git
headless
false error_go_core
fmt
os
os/exec
strings
time
name desc
cfg 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).
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. true
creates worktree dir and branch off master
ResetIfExists=true on existing branch+worktree succeeds
returns Error when RepoRoot/Branch/WorktreePath missing
functions/infra/agent_launch_worktree_test.go functions/infra/agent_launch_worktree.go

Ejemplo

res := infra.AgentLaunchWorktree(infra.WorktreeLaunchConfig{
    RepoRoot:      "/home/lucas/fn_registry",
    Branch:        "auto/0115-worktree-launcher-fn",
    WorktreePath:  "/home/lucas/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/lucas/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.