diff --git a/pkg/agentic/prep.go b/pkg/agentic/prep.go index 01ffe65..e737508 100644 --- a/pkg/agentic/prep.go +++ b/pkg/agentic/prep.go @@ -1034,6 +1034,10 @@ func (s *PrepSubsystem) buildPrompt(ctx context.Context, input PrepInput, branch // ensureWorkspaceTaskFile("/srv/.core/workspace/core/go-io/task-42") // keeps TODO.md present for the prompt and the local agent shell wrapper. func ensureWorkspaceTaskFile(workspaceDir string) error { + if workspaceDir == "" { + return core.E("prepWorkspace", "workspace dir is required", nil) + } + todoPath := core.JoinPath(workspaceDir, "TODO.md") if readResult := fs.Read(todoPath); readResult.OK && core.Trim(readResult.Value.(string)) != "" { return nil @@ -1047,7 +1051,7 @@ func ensureWorkspaceTaskFile(workspaceDir string) error { return core.E("prepWorkspace", "load TODO.md template", nil) } - if writeResult := fs.Write(todoPath, templateResult.Value.(string)); !writeResult.OK { + if writeResult := fs.WriteAtomic(todoPath, templateResult.Value.(string)); !writeResult.OK { if err, ok := writeResult.Value.(error); ok { return core.E("prepWorkspace", "write TODO.md", err) } diff --git a/pkg/agentic/prep_test.go b/pkg/agentic/prep_test.go index 0519dbf..b98e55b 100644 --- a/pkg/agentic/prep_test.go +++ b/pkg/agentic/prep_test.go @@ -1309,3 +1309,9 @@ func TestPrep_TestPrepWorkspace_Ugly(t *testing.T) { _, _, err := s.TestPrepWorkspace(context.Background(), PrepInput{Repo: ".."}) require.Error(t, err) } + +func TestPrep_EnsureWorkspaceTaskFile_Bad(t *testing.T) { + err := ensureWorkspaceTaskFile("") + require.Error(t, err) + assert.Contains(t, err.Error(), "workspace dir is required") +}