package main import ( "context" "flag" "fmt" "log" "strings" "time" "go.temporal.io/sdk/client" "github.com/rockliang/poimen/workflows/internal/config" "github.com/rockliang/poimen/workflows/statemachine" ) func main() { var ( repoPath = flag.String("repo", "", "target repo path") remoteURL = flag.String("remote", "", "remote URL") milestone = flag.String("milestone", "T0", "milestone ID") dryRun = flag.Bool("dry-run", false, "disable git push/merge") plannerModel = flag.String("planner-model", "ornith", "planner model ID") judgeModel = flag.String("judge-model", "ornith", "judge model ID") implementerModel = flag.String("implementer-model", "claude-sonnet-5", "implementer model ID") ) flag.Parse() // Validate required flags if *repoPath == "" || *remoteURL == "" { log.Fatalf("--repo and --remote flags are required") } // Load configuration cfg, err := config.LoadConfig() if err != nil { log.Fatalf("failed to load config: %v", err) } // Connect to Temporal c, err := client.Dial(client.Options{ HostPort: cfg.Temporal.HostPort, Namespace: cfg.Temporal.Namespace, }) if err != nil { log.Fatalf("failed to connect to temporal: %v", err) } defer c.Close() // Build OrchestratorInput input := statemachine.OrchestratorInput{ TargetRepoPath: *repoPath, RemoteURL: *remoteURL, Milestone: *milestone, DryRun: *dryRun, MaxCyclesBeforeCAN: 100, Config: statemachine.OrchestratorConfig{ SystemPrompt: "You are an expert software developer orchestrating multi-agent work.", Skills: []statemachine.SkillRef{}, RolePrompts: map[string]statemachine.PromptSpec{ "planner": { TemplateRef: "planner/default.tmpl", Model: statemachine.ModelSpec{ ModelID: *plannerModel, Thinking: "adaptive", Effort: "high", }, }, "judge": { TemplateRef: "judge/default.tmpl", Model: statemachine.ModelSpec{ ModelID: *judgeModel, Thinking: "adaptive", Effort: "high", }, }, "implementer": { TemplateRef: "implementer/default.tmpl", Model: statemachine.ModelSpec{ ModelID: *implementerModel, }, }, }, Tuning: statemachine.NewActivityTuning(), }, } // Start workflow workflowID := "orch-" + strings.ReplaceAll(*repoPath, "/", "-") run, err := c.ExecuteWorkflow(context.Background(), client.StartWorkflowOptions{ ID: workflowID, TaskQueue: "default", }, statemachine.OrchestratorWorkflow, input) if err != nil { log.Fatalf("failed to start workflow: %v", err) } fmt.Printf("\n=== Workflow Started ===\n") fmt.Printf("Workflow ID: %s\n", workflowID) fmt.Printf("Task Queue: default\n") fmt.Printf("\n=== Model Configuration ===\n") fmt.Printf("Planner Model: %s\n", *plannerModel) fmt.Printf("Judge Model: %s\n", *judgeModel) fmt.Printf("Implementer Model: %s\n", *implementerModel) fmt.Printf("\n=== Monitoring ===\n") fmt.Printf("Web UI: http://%s:8080/namespaces/%s/workflows/%s\n", strings.Split(cfg.Temporal.HostPort, ":")[0], cfg.Temporal.Namespace, workflowID) // Optionally wait for completion (with timeout) ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) defer cancel() var result statemachine.OrchestratorOutput if err := run.Get(ctx, &result); err != nil { fmt.Printf("\nWorkflow initiated (execution in progress).\n") fmt.Printf("Check the Web UI for real-time status updates.\n") } else { fmt.Printf("\nWorkflow completed: %+v\n", result) } }