package sdlc import "testing" // TestFullLifecycleClassification walks through the entire feature lifecycle. func TestFullLifecycleClassification(t *testing.T) { c := NewClassifier() cfg := DefaultConfig("test") state := DefaultState("test") f := makeTestFeature(PhaseDraft) // Phase: Draft // Step 1: needs spec cl := c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionCreateSpec { t.Fatalf("step1: Action = %q, want CREATE_SPEC", cl.Action) } // Step 2: spec created -> needs approval f.GetArtifact(ArtifactSpec).MarkDraft() cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionAwaitApproval { t.Fatalf("step2: Action = %q, want AWAIT_APPROVAL", cl.Action) } // Step 3: spec approved -> transition to specified f.GetArtifact(ArtifactSpec).Approve("user") cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionTransition || cl.TransitionTo != PhaseSpecified { t.Fatalf("step3: Action = %q/%q", cl.Action, cl.TransitionTo) } // Phase: Specified f.Transition(PhaseSpecified) // Step 4: needs design cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionCreateDesign { t.Fatalf("step4: Action = %q, want CREATE_DESIGN", cl.Action) } // Step 5: design approved -> needs tasks f.GetArtifact(ArtifactDesign).Approve("user") cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionCreateTasks { t.Fatalf("step5: Action = %q, want CREATE_TASKS", cl.Action) } // Step 6: tasks approved -> needs qa plan f.GetArtifact(ArtifactTasks).Approve("user") cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionCreateQAPlan { t.Fatalf("step6: Action = %q, want CREATE_QA_PLAN", cl.Action) } // Step 7: qa plan approved -> transition to planned f.GetArtifact(ArtifactQAPlan).Approve("user") cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionTransition || cl.TransitionTo != PhasePlanned { t.Fatalf("step7: Action = %q/%q", cl.Action, cl.TransitionTo) } // Phase: Planned -> needs branch -> Ready -> Implementation f.Transition(PhasePlanned) // Step 7b: needs branch (RequireBranch is true in DefaultConfig) cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionCreateBranch { t.Fatalf("step7b: Action = %q, want CREATE_BRANCH", cl.Action) } // Branch created f.Branch = "feature/auth" // Step 7c: ready to implement cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionTransition || cl.TransitionTo != PhaseReady { t.Fatalf("step7c: Action = %q/%q, want TRANSITION/ready", cl.Action, cl.TransitionTo) } f.Transition(PhaseReady) f.Transition(PhaseImplementation) // Add tasks f.Tasks = AddTask(nil, "Create user model") f.Tasks = AddTask(f.Tasks, "Add validation") // Step 8: implement next task cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionImplementTask { t.Fatalf("step8: Action = %q, want IMPLEMENT_TASK", cl.Action) } // Complete all tasks f.Tasks, _ = StartTask(f.Tasks, "task-001") f.Tasks, _ = CompleteTask(f.Tasks, "task-001") f.Tasks, _ = StartTask(f.Tasks, "task-002") f.Tasks, _ = CompleteTask(f.Tasks, "task-002") // Step 9: implementation complete -> transition to review cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionTransition || cl.TransitionTo != PhaseReview { t.Fatalf("step9: Action = %q/%q", cl.Action, cl.TransitionTo) } // Phase: Review f.Transition(PhaseReview) f.GetArtifact(ArtifactReview).MarkPassed() cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.TransitionTo != PhaseAudit { t.Fatalf("review->audit: TransitionTo = %q", cl.TransitionTo) } // Phase: Audit f.Transition(PhaseAudit) f.GetArtifact(ArtifactAudit).MarkPassed() cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.TransitionTo != PhaseQA { t.Fatalf("audit->qa: TransitionTo = %q", cl.TransitionTo) } // Phase: QA f.Transition(PhaseQA) f.GetArtifact(ArtifactQAResults).MarkPassed() cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.TransitionTo != PhaseMerge { t.Fatalf("qa->merge: TransitionTo = %q", cl.TransitionTo) } // Phase: Merge f.Transition(PhaseMerge) cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionMergeFeature { t.Fatalf("merge: Action = %q, want MERGE_FEATURE", cl.Action) } // Phase: Released f.Transition(PhaseReleased) cl = c.Classify(&EvalContext{State: state, Feature: f, Config: cfg}) if cl.Action != ActionArchive { t.Fatalf("released: Action = %q, want ARCHIVE", cl.Action) } }