launchAutoRun creates the per-run log directory, starts the detached supervisor via autoLauncher, and returns (pid, logPath). It does NOT touch the DB — the caller records the auto_run_* fields so the write is part of the same bookkeeping flow as the interactive path's post-spawn updates.
(task *flowdb.Task, root, injection string)
| 145 | return out |
| 146 | } |
| 147 | |
| 148 | // launchAutoRun creates the per-run log directory, starts the detached |
| 149 | // supervisor via autoLauncher, and returns (pid, logPath). It does NOT |
| 150 | // touch the DB — the caller records the auto_run_* fields so the write is |
| 151 | // part of the same bookkeeping flow as the interactive path's post-spawn |
| 152 | // updates. |
| 153 | func launchAutoRun(task *flowdb.Task, root, injection string) (int, string, error) { |
| 154 | runsDir := filepath.Join(root, "tasks", task.Slug, "auto-runs") |
| 155 | if err := os.MkdirAll(runsDir, 0o755); err != nil { |
| 156 | return 0, "", fmt.Errorf("mkdir %s: %w", runsDir, err) |
| 157 | } |
| 158 | // Timestamped filename (UTC) keeps a per-run log history. time.Now is |
| 159 | // fine here — this is a filename, not a slug or a stored timestamp. |
| 160 | logName := time.Now().UTC().Format("2006-01-02-150405") + ".log" |
| 161 | logPath := filepath.Join(runsDir, logName) |
| 162 | |
| 163 | pid, err := autoLauncher(task.Slug, task.WorkDir, logPath, injection, autoChildEnv()) |
| 164 | if err != nil { |
| 165 | return 0, "", err |