diff --git a/pkg/agent/instance.go b/pkg/agent/instance.go index 110dc11a7..358a38a19 100644 --- a/pkg/agent/instance.go +++ b/pkg/agent/instance.go @@ -206,16 +206,21 @@ func resolvePlanFallbacks(agentCfg *config.AgentConfig, defaults *config.AgentDe } // ActivateWorktree creates a worktree for a session. -// Path: /.picoclaw/worktrees// -func (ai *AgentInstance) ActivateWorktree(sessionKey, taskName string) (*git.WorktreeInfo, error) { - repoRoot := git.FindRepoRoot(ai.Workspace) +// projectDir is the git repository to create the worktree in. +// If empty, falls back to ai.Workspace. +// Path: /.picoclaw/worktrees// +func (ai *AgentInstance) ActivateWorktree(sessionKey, taskName, projectDir string) (*git.WorktreeInfo, error) { + if projectDir == "" { + projectDir = ai.Workspace + } + repoRoot := git.FindRepoRoot(projectDir) if repoRoot == "" { - return nil, fmt.Errorf("workspace is not a git repository") + return nil, fmt.Errorf("directory is not a git repository: %s", projectDir) } branchName := git.SanitizeBranchName(taskName) baseName := git.BranchBaseName(branchName) - wtPath := filepath.Join(ai.Workspace, ".picoclaw", "worktrees", baseName) + wtPath := filepath.Join(repoRoot, ".picoclaw", "worktrees", baseName) wt, err := git.CreateWorktree(repoRoot, wtPath, branchName) if err != nil { diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index 5f5c759e7..a49a74eb0 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -307,7 +307,8 @@ func (al *AgentLoop) Run(ctx context.Context) error { if taskName == "" { taskName = "plan-execution" } - if wt, err := agent.ActivateWorktree(msg.SessionKey, taskName); err != nil { + planDir := agent.ContextBuilder.GetPlanWorkDir() + if wt, err := agent.ActivateWorktree(msg.SessionKey, taskName, planDir); err != nil { logger.WarnCF("agent", "Worktree activation skipped", map[string]any{"error": err.Error()}) } else { logger.InfoCF("agent", "Worktree activated", map[string]any{"branch": wt.Branch}) @@ -2111,7 +2112,8 @@ func (al *AgentLoop) runLLMIteration( // Heartbeat lazy worktree: create worktree on first write-tool call if opts.Background && isWriteTool(tc.Name) && !agent.IsInWorktree(opts.SessionKey) { taskName := "heartbeat-" + time.Now().Format("20060102") - if wt, err := agent.ActivateWorktree(opts.SessionKey, taskName); err == nil { + hbDir := agent.ContextBuilder.GetPlanWorkDir() + if wt, err := agent.ActivateWorktree(opts.SessionKey, taskName, hbDir); err == nil { logger.InfoCF("agent", "Heartbeat worktree created", map[string]any{"branch": wt.Branch}) } }