80 lines
3 KiB
Go
80 lines
3 KiB
Go
package command
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// TerminalError carries a deliberate CLI exit status after the command has
|
|
// already emitted its bounded response. It is not an implementation failure.
|
|
type TerminalError struct{ Code int }
|
|
|
|
func (e *TerminalError) Error() string { return fmt.Sprintf("task-loop terminal exit %d", e.Code) }
|
|
|
|
func newTaskLoopCmd(svc Service, repoConfig, localConfig, providerCatalog, outputFormat *string) *cobra.Command {
|
|
var taskGroup string
|
|
var dryRun bool
|
|
var retryBlocked bool
|
|
command := &cobra.Command{
|
|
Use: "task-loop",
|
|
Short: "Run one authoritative task-loop operator pass",
|
|
Long: "Run one bounded operator pass over the standalone runtime. Dry-run reads the same workflow projection without starting a provider.",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
response, err := svc.TaskLoop(cmd.Context(), TaskLoopRequest{
|
|
Config: RuntimeConfigPaths{RepoGlobalPath: *repoConfig, UserLocalPath: *localConfig, ProviderCatalog: *providerCatalog},
|
|
TaskGroup: taskGroup, DryRun: dryRun, RetryBlocked: retryBlocked,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("task-loop: %w", err)
|
|
}
|
|
if err := printOutput(cmd, response, *outputFormat); err != nil {
|
|
return err
|
|
}
|
|
if response.ExitCode != 0 {
|
|
return &TerminalError{Code: response.ExitCode}
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
command.Flags().StringVar(&taskGroup, "task-group", "", "exact m- prefixed task group to operate")
|
|
command.Flags().BoolVar(&dryRun, "dry-run", false, "inspect the workflow projection without provider execution")
|
|
command.Flags().BoolVar(&retryBlocked, "retry-blocked", false, "resume only explicitly selected blocked projects")
|
|
parity := &cobra.Command{
|
|
Use: "parity",
|
|
Short: "Validate the S13 parity and disposal manifest",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
disposalManifest, err := cmd.Flags().GetBool("disposal-manifest")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !disposalManifest {
|
|
return fmt.Errorf("parity requires --disposal-manifest")
|
|
}
|
|
return svc.TaskLoopParity(cmd.Context(), cmd.OutOrStdout())
|
|
},
|
|
}
|
|
parity.Flags().Bool("disposal-manifest", false, "validate the checksum-bound disposal manifest")
|
|
command.AddCommand(parity)
|
|
validatePlan := &cobra.Command{
|
|
Use: "validate-plan [plan]",
|
|
Short: "Validate a PLAN write set without starting a runtime",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
workspace, err := cmd.Flags().GetString("workspace")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := svc.ValidatePlan(cmd.Context(), PlanValidationRequest{Workspace: workspace, PlanPath: args[0]}); err != nil {
|
|
return fmt.Errorf("validate-plan: %w", err)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
validatePlan.Flags().String("workspace", "", "absolute workspace that contains every declared write target")
|
|
_ = validatePlan.MarkFlagRequired("workspace")
|
|
command.AddCommand(validatePlan)
|
|
return command
|
|
}
|