From 3962597950421e422b6e1ce57764550f5600ded6 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Tue, 3 Mar 2026 21:22:30 +0000 Subject: Fix working_dir failures: validate path early, remove hardcoded /root executor/claude.go: stat working_dir before cmd.Start() so a missing or inaccessible directory surfaces as a clear error ("working_dir \"/bad/path\": no such file or directory") rather than an opaque chdir failure wrapped in "starting claude". api/elaborate.go: replace the hardcoded /root/workspace/claudomator path with buildElaboratePrompt(workDir) which injects the server's actual working directory (from os.Getwd() at startup). Empty workDir tells the model to leave working_dir blank. Co-Authored-By: Claude Sonnet 4.6 --- internal/api/elaborate.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'internal/api/elaborate.go') diff --git a/internal/api/elaborate.go b/internal/api/elaborate.go index 357bf3c..d275d61 100644 --- a/internal/api/elaborate.go +++ b/internal/api/elaborate.go @@ -13,12 +13,15 @@ import ( const elaborateTimeout = 30 * time.Second -const elaborateSystemPrompt = `You are a task configuration assistant for Claudomator, an AI task runner that executes tasks by running Claude as a subprocess. +func buildElaboratePrompt(workDir string) string { + workDirLine := ` "working_dir": string — leave empty unless you have a specific reason to set it,` + if workDir != "" { + workDirLine = fmt.Sprintf(` "working_dir": string — use %q for tasks that operate on this codebase, empty string otherwise,`, workDir) + } + return `You are a task configuration assistant for Claudomator, an AI task runner that executes tasks by running Claude as a subprocess. Your ONLY job is to convert any user request into a Claudomator task JSON object. You MUST always output valid JSON. Never ask clarifying questions. Never explain. Never refuse. Make reasonable assumptions and produce the JSON. -If the request is about Claudomator itself (e.g. "add a feature", "fix a bug", "hide completed tasks"), treat it as a software engineering task to be implemented in the Claudomator codebase at /root/workspace/claudomator. - Output ONLY a valid JSON object matching this schema (no markdown fences, no prose, no explanation): { @@ -27,7 +30,7 @@ Output ONLY a valid JSON object matching this schema (no markdown fences, no pro "claude": { "model": string — "sonnet" unless the task obviously needs opus, "instructions": string — detailed, step-by-step instructions for Claude, - "working_dir": string — use "/root/workspace/claudomator" for Claudomator tasks, empty string otherwise, +` + workDirLine + ` "max_budget_usd": number — conservative estimate (0.25–5.00), "allowed_tools": array — only tools the task genuinely needs }, @@ -35,6 +38,7 @@ Output ONLY a valid JSON object matching this schema (no markdown fences, no pro "priority": string — "normal" | "high" | "low", "tags": array — relevant lowercase tags }` +} // elaboratedTask mirrors the task creation schema for elaboration responses. type elaboratedTask struct { @@ -98,7 +102,7 @@ func (s *Server) handleElaborateTask(w http.ResponseWriter, r *http.Request) { cmd := exec.CommandContext(ctx, s.claudeBinaryPath(), "-p", input.Prompt, - "--system-prompt", elaborateSystemPrompt, + "--system-prompt", buildElaboratePrompt(s.workDir), "--output-format", "json", "--model", "haiku", ) -- cgit v1.2.3