summaryrefslogtreecommitdiff
path: root/internal/executor/executor.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-03-05 23:03:02 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-03-05 23:03:02 +0000
commitf8b5f2580e730a8affbccec8b5bde9b96b1f9fc2 (patch)
tree8bee6ccf9f4dff4d705c09c6b6a9e94967c58c4e /internal/executor/executor.go
parented6cb17501bd14ce5ec009f68fba54539cf1a470 (diff)
executor: persist log paths at execution create time, not just at end
Add LogPather interface; ClaudeRunner implements it via ExecLogDir(). Pool pre-populates stdout_path/stderr_path/artifact_dir on the execution record before CreateExecution, so paths are in the DB from the moment a task starts running. ClaudeRunner.Run() skips path assignment when already set by the pool. Also update scripts/debug-execution to derive paths from the known convention (<data-dir>/executions/<exec-id>/) as a fallback for historical records that predate this change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/executor/executor.go')
-rw-r--r--internal/executor/executor.go18
1 files changed, 18 insertions, 0 deletions
diff --git a/internal/executor/executor.go b/internal/executor/executor.go
index 51f468e..eb23c02 100644
--- a/internal/executor/executor.go
+++ b/internal/executor/executor.go
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log/slog"
+ "path/filepath"
"sync"
"time"
@@ -12,6 +13,13 @@ import (
"github.com/google/uuid"
)
+// LogPather is an optional interface runners can implement to provide the log
+// directory for an execution before it starts. The pool uses this to persist
+// log paths at CreateExecution time rather than waiting until execution ends.
+type LogPather interface {
+ ExecLogDir(execID string) string
+}
+
// Runner executes a single task and returns the result.
type Runner interface {
Run(ctx context.Context, t *task.Task, exec *storage.Execution) error
@@ -115,6 +123,16 @@ func (p *Pool) execute(ctx context.Context, t *task.Task) {
Status: "RUNNING",
}
+ // Pre-populate log paths so they're available in the DB immediately —
+ // before the subprocess starts — enabling live tailing and debugging.
+ if lp, ok := p.runner.(LogPather); ok {
+ if logDir := lp.ExecLogDir(execID); logDir != "" {
+ exec.StdoutPath = filepath.Join(logDir, "stdout.log")
+ exec.StderrPath = filepath.Join(logDir, "stderr.log")
+ exec.ArtifactDir = logDir
+ }
+ }
+
// Record execution start.
if err := p.store.CreateExecution(exec); err != nil {
p.logger.Error("failed to create execution record", "error", err)