// Package supervisor implements the KAOS supervisor process // that orchestrates agent execution and task management. package supervisor import ( "fmt" "path/filepath" "github.com/dal/kaos/internal/config" ) // Supervisor orchestrates task execution, verification, and reporting. type Supervisor struct { Config *config.Config TasksDir string CodeDir string ReportsDir string CmdBuilder CommandBuilder } // NewSupervisor creates a Supervisor from configuration. func NewSupervisor(cfg *config.Config) *Supervisor { return &Supervisor{ Config: cfg, TasksDir: cfg.TasksDir, CodeDir: cfg.ProjectPath, ReportsDir: filepath.Join(cfg.TasksDir, "reports"), } } // Run executes a specific task by ID through the full pipeline: // scan → find → move to active → run → verify → report → move to review. func (s *Supervisor) Run(taskID string) error { tasks, err := ScanTasks(s.TasksDir) if err != nil { return fmt.Errorf("scan tasks: %w", err) } task := FindTask(tasks, taskID) if task == nil { return fmt.Errorf("task %s nije pronađen", taskID) } if task.Status != "ready" { return fmt.Errorf("task %s nije u ready/ (trenutno: %s)", taskID, task.Status) } return s.execute(task) } // RunNext finds the next ready task with satisfied dependencies and runs it. func (s *Supervisor) RunNext() error { tasks, err := ScanTasks(s.TasksDir) if err != nil { return fmt.Errorf("scan tasks: %w", err) } task := NextTask(tasks) if task == nil { return fmt.Errorf("nema taskova spremnih za rad") } return s.execute(task) } // execute runs the full pipeline for a task. func (s *Supervisor) execute(task *Task) error { // Move to active if err := MoveTask(s.TasksDir, task.ID, "ready", "active"); err != nil { return fmt.Errorf("premesti u active/: %w", err) } // Run the task result := RunTask(*task, s.CodeDir, s.Config.Timeout, s.CmdBuilder) // Verify verify := Verify(s.CodeDir) // Write report _, err := WriteReport(*task, result, verify, s.ReportsDir) if err != nil { // Don't fail the pipeline for report errors, but log it fmt.Printf("Upozorenje: greška pri pisanju izveštaja: %v\n", err) } // Move to review (regardless of pass/fail) if err := MoveTask(s.TasksDir, task.ID, "active", "review"); err != nil { return fmt.Errorf("premesti u review/: %w", err) } if !verify.AllPassed { return fmt.Errorf("verifikacija neuspešna za %s", task.ID) } return nil }