From 1b5e7177769c79f9e836a55f9c008a295e2ff975 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Wed, 11 Mar 2026 07:40:48 +0000 Subject: fix: resume BLOCKED tasks in preserved sandbox so Claude finds its session MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a task ran in a sandbox (/tmp/claudomator-sandbox-*) and went BLOCKED, Claude stored its session under the sandbox path as the project slug. The resume execution was running in project_dir, causing Claude to look for the session in the wrong project directory and fail with "No conversation found". Fix: carry SandboxDir through BlockedError → Execution → resume execution, and run the resume in that directory so the session lookup succeeds. - BlockedError gains SandboxDir field; claude.go sets it on BLOCKED exit - storage.Execution gains SandboxDir (persisted via new sandbox_dir column) - executor.go stores blockedErr.SandboxDir in the execution record - server.go copies SandboxDir from latest execution to the resume execution - claude.go uses e.SandboxDir as working dir for resume when set Co-Authored-By: Claude Sonnet 4.6 --- internal/executor/executor.go | 1 + 1 file changed, 1 insertion(+) (limited to 'internal/executor/executor.go') diff --git a/internal/executor/executor.go b/internal/executor/executor.go index f54773a..76c8ac7 100644 --- a/internal/executor/executor.go +++ b/internal/executor/executor.go @@ -273,6 +273,7 @@ func (p *Pool) handleRunResult(ctx context.Context, t *task.Task, exec *storage. var blockedErr *BlockedError if errors.As(err, &blockedErr) { exec.Status = "BLOCKED" + exec.SandboxDir = blockedErr.SandboxDir // preserve so resume runs in same dir if err := p.store.UpdateTaskState(t.ID, task.StateBlocked); err != nil { p.logger.Error("failed to update task state", "taskID", t.ID, "state", task.StateBlocked, "error", err) } -- cgit v1.2.3