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/internal/health" "github.com/rockliang/poimen/workflows/internal/logging" "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") healthCheck = flag.Bool("health", false, "check health and exit") ) flag.Parse() // Initialize structured logging if err := logging.InitLogger(); err != nil { log.Fatalf("failed to initialize logger: %v", err) } defer logging.Sync() // Load configuration first cfg, err := config.LoadConfig() if err != nil { logging.Fatal("failed to load config", logging.Err(err)) } // Connect to Temporal logging.Info("connecting to Temporal", logging.String("hostPort", cfg.Temporal.HostPort), logging.String("namespace", cfg.Temporal.Namespace)) c, err := client.Dial(client.Options{ HostPort: cfg.Temporal.HostPort, Namespace: cfg.Temporal.Namespace, }) if err != nil { logging.Fatal("failed to connect to temporal", logging.Err(err)) } defer c.Close() // If health check requested, do it and exit if *healthCheck { logging.Info("running health check") healthChecker := health.NewChecker(c) report := healthChecker.Check(context.Background()) jsonReport, _ := report.ToJSON() fmt.Println(string(jsonReport)) if report.Status != health.StatusHealthy { logging.Fatal("health check failed") } return } // Validate required flags for workflow start if *repoPath == "" || *remoteURL == "" { logging.Fatal("--repo and --remote flags are required") } // 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, "/", "-") logging.Info("starting orchestrator workflow", logging.String("workflowID", workflowID), logging.String("repo", *repoPath)) run, err := c.ExecuteWorkflow(context.Background(), client.StartWorkflowOptions{ ID: workflowID, TaskQueue: "poimen-taskqueue", }, statemachine.OrchestratorWorkflow, input) if err != nil { logging.Fatal("failed to start workflow", logging.Err(err)) } fmt.Printf("\n=== Workflow Started ===\n") fmt.Printf("Workflow ID: %s\n", workflowID) fmt.Printf("Task Queue: poimen-taskqueue\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) } }