package sdlc import "fmt" // Execution phase rules: review, audit, QA, merge, archive. func needsReviewRule() Rule { return Rule{ ID: "needs-review", Condition: func(ctx *EvalContext) bool { if ctx.Feature.Phase != PhaseReview { return false } art := ctx.Feature.GetArtifact(ArtifactReview) return art == nil || art.Status == StatusPending }, Action: ActionReviewCode, NextCommand: func(ctx *EvalContext) string { return "/review-feature " + ctx.Feature.Slug }, OutputPath: func(ctx *EvalContext) string { return ".sdlc/features/" + ctx.Feature.Slug + "/review.md" }, } } func reviewHasIssuesRule() Rule { return Rule{ ID: "review-has-issues", Condition: func(ctx *EvalContext) bool { if ctx.Feature.Phase != PhaseReview { return false } art := ctx.Feature.GetArtifact(ArtifactReview) return art != nil && art.Status == StatusNeedsFix }, Action: ActionFixReviewIssues, NextCommand: func(ctx *EvalContext) string { return "/fix-review-issues " + ctx.Feature.Slug }, } } func reviewPassedRule() Rule { return Rule{ ID: "review-passed", Condition: func(ctx *EvalContext) bool { if ctx.Feature.Phase != PhaseReview { return false } art := ctx.Feature.GetArtifact(ArtifactReview) return art != nil && art.Status == StatusPassed }, Action: ActionTransition, TransitionTo: PhaseAudit, } } func needsAuditRule() Rule { return Rule{ ID: "needs-audit", Condition: func(ctx *EvalContext) bool { if ctx.Feature.Phase != PhaseAudit { return false } art := ctx.Feature.GetArtifact(ArtifactAudit) return art == nil || art.Status == StatusPending }, Action: ActionAuditCode, NextCommand: func(ctx *EvalContext) string { return "/audit-feature " + ctx.Feature.Slug }, OutputPath: func(ctx *EvalContext) string { return ".sdlc/features/" + ctx.Feature.Slug + "/audit.md" }, } } func auditHasIssuesRule() Rule { return Rule{ ID: "audit-has-issues", Condition: func(ctx *EvalContext) bool { if ctx.Feature.Phase != PhaseAudit { return false } art := ctx.Feature.GetArtifact(ArtifactAudit) return art != nil && art.Status == StatusNeedsFix }, Action: ActionRemediateAudit, NextCommand: func(ctx *EvalContext) string { return "/remediate-audit " + ctx.Feature.Slug }, } } func auditPassedRule() Rule { return Rule{ ID: "audit-passed", Condition: func(ctx *EvalContext) bool { if ctx.Feature.Phase != PhaseAudit { return false } art := ctx.Feature.GetArtifact(ArtifactAudit) return art != nil && art.Status == StatusPassed }, Action: ActionTransition, TransitionTo: PhaseQA, } } func needsQARule() Rule { return Rule{ ID: "needs-qa", Condition: func(ctx *EvalContext) bool { if ctx.Feature.Phase != PhaseQA { return false } art := ctx.Feature.GetArtifact(ArtifactQAResults) return art == nil || art.Status == StatusPending }, Action: ActionRunQA, NextCommand: func(ctx *EvalContext) string { return "/run-qa " + ctx.Feature.Slug }, OutputPath: func(ctx *EvalContext) string { return ".sdlc/features/" + ctx.Feature.Slug + "/qa-results.md" }, } } func qaHasFailuresRule() Rule { return Rule{ ID: "qa-has-failures", Condition: func(ctx *EvalContext) bool { if ctx.Feature.Phase != PhaseQA { return false } art := ctx.Feature.GetArtifact(ArtifactQAResults) return art != nil && art.Status == StatusFailed }, Action: ActionFixQAFailures, NextCommand: func(ctx *EvalContext) string { return "/fix-qa-failures " + ctx.Feature.Slug }, } } func qaPassedRule() Rule { return Rule{ ID: "qa-passed", Condition: func(ctx *EvalContext) bool { if ctx.Feature.Phase != PhaseQA { return false } art := ctx.Feature.GetArtifact(ArtifactQAResults) return art != nil && art.Status == StatusPassed }, Action: ActionTransition, TransitionTo: PhaseMerge, } } func needsMergeRule() Rule { return Rule{ ID: "needs-merge", Condition: func(ctx *EvalContext) bool { return ctx.Feature.Phase == PhaseMerge }, Action: ActionMergeFeature, NextCommand: func(ctx *EvalContext) string { return "/merge-feature " + ctx.Feature.Slug }, } } func archiveFeatureRule() Rule { return Rule{ ID: "archive-feature", Condition: func(ctx *EvalContext) bool { return ctx.Feature.Phase == PhaseReleased }, Action: ActionArchive, NextCommand: func(ctx *EvalContext) string { return "/archive-feature " + ctx.Feature.Slug }, } } func implementNextTaskRule() Rule { return Rule{ ID: "implement-next-task", Condition: func(ctx *EvalContext) bool { if ctx.Feature.Phase != PhaseImplementation { return false } next := NextTask(ctx.Feature.Tasks) return next != nil }, Action: ActionImplementTask, NextCommand: func(ctx *EvalContext) string { next := NextTask(ctx.Feature.Tasks) if next == nil { return "" } return fmt.Sprintf("/implement-task %s %s", ctx.Feature.Slug, next.ID) }, OutputPath: func(ctx *EvalContext) string { return ".sdlc/features/" + ctx.Feature.Slug + "/tasks.md" }, TaskID: func(ctx *EvalContext) string { next := NextTask(ctx.Feature.Tasks) if next == nil { return "" } return next.ID }, } } func implementationCompleteRule() Rule { return Rule{ ID: "implementation-complete", Condition: func(ctx *EvalContext) bool { return ctx.Feature.Phase == PhaseImplementation && AllTasksComplete(ctx.Feature.Tasks) }, Action: ActionTransition, TransitionTo: PhaseReview, } }