package orch import ( "fmt" "ai-workflow-skill/packages/coord-core/protocol" "ai-workflow-skill/packages/coord-core/store" "github.com/spf13/cobra" ) type dispatchOptions struct { runID string taskID string toAgent string body string bodyFile string executionMode string baseRef string repoPath string workspaceRoot string } func newDispatchCmd(root *rootOptions) *cobra.Command { opts := &dispatchOptions{} cmd := &cobra.Command{ Use: "dispatch", Short: "Dispatch a ready task to a worker through inbox", Long: helpLong( "Use dispatch to turn one ready task into a concrete attempt and inbox thread.", "You must choose exactly one execution mode.", "analysis: create the attempt and thread only; do not allocate a worktree.", "code: allocate a Git worktree for the attempt and record workspace metadata.", "repo-path, workspace-root, and base-ref only apply to execution-mode code.", "dispatch creates handoff state only; a separate worker runtime or worker agent must still claim the assigned inbox thread.", ), Example: ` orch --db .agents/coord.db dispatch --run blog_mvp_001 --task T1 --execution-mode analysis --to qa-worker --body "Summarize the latest failures." orch --db .agents/coord.db dispatch --run blog_mvp_001 --task T2 --execution-mode code --to backend-worker --repo-path /path/to/repo --workspace-root .orch/worktrees --base-ref main --body-file ./tasks/t2.md`, RunE: func(cmd *cobra.Command, args []string) error { normalizedOpts, err := normalizeDispatchOptions(*opts) if err != nil { return err } body, err := resolveBodyValue(opts.body, opts.bodyFile) if err != nil { return err } ctx := cmd.Context() sqlDB, err := openOrchDB(ctx, root.dbPath) if err != nil { return err } defer sqlDB.Close() result, err := store.NewOrchStore(sqlDB).DispatchTask(ctx, store.DispatchInput{ RunID: normalizedOpts.runID, TaskID: normalizedOpts.taskID, ToAgent: normalizedOpts.toAgent, Body: body, BaseRef: normalizedOpts.baseRef, PrepareWorkspace: newDispatchWorkspacePreparer(cmd, normalizedOpts), }) if err != nil { return err } resp := protocol.Success{ OK: true, Command: "dispatch", Data: map[string]any{ "task": result.Task, "attempt": result.Attempt, "thread": result.Thread, "message": result.Message, }, } if root.json { return protocol.WriteJSON(cmd.OutOrStdout(), resp) } _, err = fmt.Fprintf( cmd.OutOrStdout(), "dispatched task %s to %s as thread %s\n", result.Task.TaskID, result.Attempt.AssignedTo, result.Attempt.ThreadID, ) return err }, } cmd.Flags().StringVar(&opts.runID, "run", "", "Run ID") cmd.Flags().StringVar(&opts.taskID, "task", "", "Task ID") cmd.Flags().StringVar(&opts.toAgent, "to", "", "Worker agent override") cmd.Flags().StringVar(&opts.body, "body", "", "Task message body") cmd.Flags().StringVar(&opts.bodyFile, "body-file", "", "Read task message body from file") cmd.Flags().StringVar(&opts.executionMode, "execution-mode", "", "Execution mode: analysis or code") cmd.Flags().StringVar(&opts.baseRef, "base-ref", "", "Optional base ref to record on the attempt") cmd.Flags().StringVar(&opts.repoPath, "repo-path", "", "Source repository path for worktree dispatch") cmd.Flags().StringVar(&opts.workspaceRoot, "workspace-root", "", "Workspace root for worktree dispatch") _ = cmd.MarkFlagRequired("run") _ = cmd.MarkFlagRequired("task") _ = cmd.MarkFlagRequired("execution-mode") return cmd }