Add subtask generation decision

Change-Id: If43efa882de08bc262fe6117af7307e97c4dfeda
diff --git a/server/subtasks/service_test.go b/server/subtasks/service_test.go
index 1d94211..ade62fc 100644
--- a/server/subtasks/service_test.go
+++ b/server/subtasks/service_test.go
@@ -95,6 +95,38 @@
 	}
 }
 
+func TestShouldGenerateSubtasks(t *testing.T) {
+	// Test decision to generate subtasks
+	decisionResponse := `{
+  "needs_subtasks": true,
+  "reasoning": "Complex task requiring multiple skills",
+  "complexity_score": 8,
+  "required_skills": ["backend", "frontend", "database"]
+}`
+
+	mockProvider := NewMockLLMProvider([]string{decisionResponse})
+	agentRoles := []string{"backend", "frontend", "qa"}
+	service := NewSubtaskService(mockProvider, nil, agentRoles)
+	
+	// Test the parseSubtaskDecision method directly since ShouldGenerateSubtasks is used by manager
+	decision, err := service.parseSubtaskDecision(decisionResponse)
+	if err != nil {
+		t.Fatalf("parseSubtaskDecision failed: %v", err)
+	}
+	
+	if !decision.NeedsSubtasks {
+		t.Error("Expected decision to need subtasks")
+	}
+	
+	if decision.ComplexityScore != 8 {
+		t.Errorf("Expected complexity score 8, got %d", decision.ComplexityScore)
+	}
+	
+	if len(decision.RequiredSkills) != 3 {
+		t.Errorf("Expected 3 required skills, got %d", len(decision.RequiredSkills))
+	}
+}
+
 func TestAnalyzeTaskForSubtasks(t *testing.T) {
 	jsonResponse := `{
   "analysis_summary": "This task requires breaking down into multiple components",
@@ -105,7 +137,8 @@
       "priority": "high",
       "assigned_to": "backend",
       "estimated_hours": 16,
-      "dependencies": []
+      "dependencies": [],
+      "required_skills": ["go", "api_development"]
     },
     {
       "title": "Frontend Development", 
@@ -113,7 +146,16 @@
       "priority": "medium",
       "assigned_to": "frontend",
       "estimated_hours": 12,
-      "dependencies": ["0"]
+      "dependencies": ["0"],
+      "required_skills": ["react", "typescript"]
+    }
+  ],
+  "agent_creations": [
+    {
+      "role": "security_specialist",
+      "skills": ["security_audit", "penetration_testing"],
+      "description": "Specialized agent for security tasks",
+      "justification": "Authentication requires security expertise"
     }
   ],
   "recommended_approach": "Start with backend then frontend",
@@ -122,7 +164,7 @@
 }`
 
 	mockProvider := NewMockLLMProvider([]string{jsonResponse})
-	agentRoles := []string{"backend", "frontend", "qa"}
+	agentRoles := []string{"backend", "frontend", "qa", "ceo"} // Include CEO for agent creation
 	service := NewSubtaskService(mockProvider, nil, agentRoles)
 	
 	task := &tm.Task{
@@ -148,12 +190,39 @@
 		t.Error("Analysis summary should not be empty")
 	}
 	
-	if len(analysis.Subtasks) != 2 {
-		t.Errorf("Expected 2 subtasks, got %d", len(analysis.Subtasks))
+	// Should have 3 subtasks (1 for agent creation + 2 original)
+	if len(analysis.Subtasks) != 3 {
+		t.Errorf("Expected 3 subtasks (including agent creation), got %d", len(analysis.Subtasks))
+		t.Logf("Subtasks: %+v", analysis.Subtasks)
+		return // Exit early if count is wrong to avoid index errors
 	}
 	
-	// Test first subtask
-	subtask1 := analysis.Subtasks[0]
+	// Test agent creation was processed
+	if len(analysis.AgentCreations) != 1 {
+		t.Errorf("Expected 1 agent creation, got %d", len(analysis.AgentCreations))
+	} else {
+		agentCreation := analysis.AgentCreations[0]
+		if agentCreation.Role != "security_specialist" {
+			t.Errorf("Expected role 'security_specialist', got %s", agentCreation.Role)
+		}
+		if len(agentCreation.Skills) != 2 {
+			t.Errorf("Expected 2 skills, got %d", len(agentCreation.Skills))
+		}
+	}
+
+	// We already checked the count above
+
+	// Test first subtask (agent creation)
+	subtask0 := analysis.Subtasks[0]
+	if !strings.Contains(subtask0.Title, "Security_specialist") {
+		t.Errorf("Expected agent creation subtask for security_specialist, got %s", subtask0.Title)
+	}
+	if subtask0.AssignedTo != "ceo" {
+		t.Errorf("Expected agent creation assigned to 'ceo', got %s", subtask0.AssignedTo)
+	}
+
+	// Test second subtask (original backend task, now at index 1)
+	subtask1 := analysis.Subtasks[1]
 	if subtask1.Title != "Backend Development" {
 		t.Errorf("Expected title 'Backend Development', got %s", subtask1.Title)
 	}
@@ -166,19 +235,27 @@
 	if subtask1.EstimatedHours != 16 {
 		t.Errorf("Expected 16 hours, got %d", subtask1.EstimatedHours)
 	}
+	if len(subtask1.RequiredSkills) != 2 {
+		t.Errorf("Expected 2 required skills, got %d", len(subtask1.RequiredSkills))
+	}
 	
-	// Test second subtask
-	subtask2 := analysis.Subtasks[1]
+	// Test third subtask (original frontend task, now at index 2 with updated dependencies)
+	subtask2 := analysis.Subtasks[2]
 	if subtask2.Title != "Frontend Development" {
 		t.Errorf("Expected title 'Frontend Development', got %s", subtask2.Title)
 	}
 	if subtask2.Priority != tm.PriorityMedium {
 		t.Errorf("Expected medium priority, got %s", subtask2.Priority)
 	}
-	if len(subtask2.Dependencies) != 1 || subtask2.Dependencies[0] != "0" {
-		t.Errorf("Expected dependencies [0], got %v", subtask2.Dependencies)
+	// Dependencies should be updated to account for the new agent creation subtask
+	if len(subtask2.Dependencies) != 1 || subtask2.Dependencies[0] != "1" {
+		t.Errorf("Expected dependencies [1] (updated for agent creation), got %v", subtask2.Dependencies)
+	}
+	if len(subtask2.RequiredSkills) != 2 {
+		t.Errorf("Expected 2 required skills, got %d", len(subtask2.RequiredSkills))
 	}
 	
+	// Total hours should include agent creation time (4 hours)
 	if analysis.EstimatedTotalHours != 28 {
 		t.Errorf("Expected 28 total hours, got %d", analysis.EstimatedTotalHours)
 	}