From 5814e7d6bdec659bb8ca10cc18447a821c59ad4c Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Wed, 18 Mar 2026 00:52:49 +0000 Subject: fix: comprehensive addressing of container execution review feedback - Fix Critical Bug 1: Only remove workspace on success, preserve on failure/BLOCKED. - Fix Critical Bug 2: Use correct Claude flag (--resume) and pass instructions via file. - Fix Critical Bug 3: Actually mount and use the instructions file in the container. - Address Design Issue 4: Implement Resume/BLOCKED detection and host-side workspace re-use. - Address Design Issue 5: Consolidate RepositoryURL to Task level and fix API fallback. - Address Design Issue 6: Make agent images configurable per runner type via CLI flags. - Address Design Issue 7: Secure API keys via .claudomator-env file and --env-file flag. - Address Code Quality 8: Add unit tests for ContainerRunner arg construction. - Address Code Quality 9: Fix indentation regression in app.js. - Address Code Quality 10: Clean up orphaned Claude/Gemini runner files and move helpers. - Fix tests: Update server_test.go and executor_test.go to work with new model. --- internal/executor/container_test.go | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 internal/executor/container_test.go (limited to 'internal/executor/container_test.go') diff --git a/internal/executor/container_test.go b/internal/executor/container_test.go new file mode 100644 index 0000000..b1513ea --- /dev/null +++ b/internal/executor/container_test.go @@ -0,0 +1,65 @@ +package executor + +import ( + "strings" + "testing" + + "github.com/thepeterstone/claudomator/internal/task" +) + +func TestContainerRunner_BuildDockerArgs(t *testing.T) { + runner := &ContainerRunner{ + APIURL: "http://localhost:8484", + DropsDir: "/data/drops", + } + workspace := "/tmp/ws" + taskID := "task-123" + + args := runner.buildDockerArgs(workspace, taskID) + + expected := []string{ + "run", "--rm", + "-v", "/tmp/ws:/workspace", + "-w", "/workspace", + "--env-file", "/workspace/.claudomator-env", + "-e", "CLAUDOMATOR_API_URL=http://localhost:8484", + "-e", "CLAUDOMATOR_TASK_ID=task-123", + "-e", "CLAUDOMATOR_DROP_DIR=/data/drops", + } + + if len(args) != len(expected) { + t.Fatalf("expected %d args, got %d", len(expected), len(args)) + } + for i, v := range args { + if v != expected[i] { + t.Errorf("arg %d: expected %q, got %q", i, expected[i], v) + } + } +} + +func TestContainerRunner_BuildInnerCmd(t *testing.T) { + runner := &ContainerRunner{} + + t.Run("claude", func(t *testing.T) { + tk := &task.Task{Agent: task.AgentConfig{Type: "claude"}} + cmd := runner.buildInnerCmd(tk, "exec-456") + + cmdStr := strings.Join(cmd, " ") + if !strings.Contains(cmdStr, "--resume exec-456") { + t.Errorf("expected --resume flag, got %q", cmdStr) + } + if !strings.Contains(cmdStr, "-p /workspace/.claudomator-instructions.txt") { + t.Errorf("expected instructions file path, got %q", cmdStr) + } + }) + + t.Run("gemini", func(t *testing.T) { + tk := &task.Task{Agent: task.AgentConfig{Type: "gemini"}} + cmd := runner.buildInnerCmd(tk, "exec-456") + + cmdStr := strings.Join(cmd, " ") + if !strings.HasPrefix(cmdStr, "gemini") { + t.Errorf("expected gemini command, got %q", cmdStr) + } + }) +} -- cgit v1.2.3