package domain import ( "errors" "git.cin.su/m/Assistant/contracts/work" ) var ErrGovernedEvolution = errors.New("governed evolution gate failed") func RunGovernedEvolution(needRef string, ops work.GovernedEvolutionOps) (work.GovernedEvolutionResult, error) { result := work.GovernedEvolutionResult{NeedRef: needRef, Stages: []work.EvolutionRunStage{work.EvolutionNeedRecorded}} if needRef == "" || ops.CreateCandidate == nil || ops.Evaluate == nil || ops.SandboxBuild == nil || ops.Benchmark == nil || ops.Promote == nil || ops.Rollback == nil || ops.LearningLedgerOutcome == nil { return result, ErrGovernedEvolution } candidate, err := ops.CreateCandidate() if err != nil { return result, err } if candidate.ID == "" || candidate.ProposalRef == "" { return result, ErrGovernedEvolution } result.CandidateRef = candidate.ID result.Stages = append(result.Stages, work.EvolutionCandidateBuilt) evaluation, err := ops.Evaluate(candidate) if err != nil || !evaluation.ValidFor(candidate) { return result, ErrGovernedEvolution } result.EvaluationRef = evaluation.CandidateRef result.Stages = append(result.Stages, work.EvolutionIndependentlyEvaluated) sandboxEvidence, err := ops.SandboxBuild(candidate) if err != nil || sandboxEvidence == "" { return result, ErrGovernedEvolution } candidate.SandboxEvidenceRefs = append(candidate.SandboxEvidenceRefs, sandboxEvidence) result.EvidenceRefs = append(result.EvidenceRefs, sandboxEvidence) result.Stages = append(result.Stages, work.EvolutionSandboxed) benchmarkEvidence, passed, err := ops.Benchmark(candidate) if err != nil || !passed || benchmarkEvidence == "" { result = rollbackEvolution(result, candidate, ops) return result, ErrGovernedEvolution } candidate.BenchmarkEvidenceRefs = append(candidate.BenchmarkEvidenceRefs, benchmarkEvidence) result.EvidenceRefs = append(result.EvidenceRefs, benchmarkEvidence) result.Stages = append(result.Stages, work.EvolutionBenchmarked) if ops.Canary != nil { canaryEvidence, passed, canaryErr := ops.Canary(candidate) if canaryErr != nil || !passed || canaryEvidence == "" { result = rollbackEvolution(result, candidate, ops) return result, ErrGovernedEvolution } result.EvidenceRefs = append(result.EvidenceRefs, canaryEvidence) result.Stages = append(result.Stages, work.EvolutionCanaried) } promotionRef, err := ops.Promote(candidate, evaluation) if err != nil || promotionRef == "" { result = rollbackEvolution(result, candidate, ops) return result, ErrGovernedEvolution } result.Promoted = true result.Stages = append(result.Stages, work.EvolutionPromoted) result.LearningLedgerOutcomeRef, err = ops.LearningLedgerOutcome(result) if err != nil || result.LearningLedgerOutcomeRef == "" { return result, ErrGovernedEvolution } return result, nil } func rollbackEvolution(result work.GovernedEvolutionResult, candidate work.EvolutionCandidate, ops work.GovernedEvolutionOps) work.GovernedEvolutionResult { ref, err := ops.Rollback(candidate) if err == nil && ref != "" { result.RollbackRef = ref result.Stages = append(result.Stages, work.EvolutionRolledBack) result.LearningLedgerOutcomeRef, _ = ops.LearningLedgerOutcome(result) } return result }