Skip to main content

argentor_orchestrator/
dev_team.rs

1//! Development team orchestration module.
2//!
3//! Provides pre-configured development team compositions and workflows for
4//! common coding tasks: implement feature, fix bug, refactor, security audit,
5//! add tests, code review, optimize, and write documentation.
6//!
7//! Each workflow defines a sequence of [`WorkflowStep`]s with role assignments,
8//! quality gates, and handoff rules. The [`DevTeam`] struct coordinates these
9//! workflows using the existing [`AgentRole`](crate::types::AgentRole) and
10//! [`AgentProfile`](crate::types::AgentProfile) infrastructure.
11
12use serde::{Deserialize, Serialize};
13use std::fmt;
14
15/// A role in a development team.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
17#[serde(rename_all = "snake_case")]
18pub enum DevRole {
19    /// Plans architecture and decomposes tasks.
20    Architect,
21    /// Writes production code.
22    Implementer,
23    /// Writes and runs tests.
24    Tester,
25    /// Reviews code for quality, security, and style.
26    Reviewer,
27    /// Diagnoses and fixes bugs.
28    Debugger,
29    /// Handles CI/CD, deployment, infrastructure.
30    DevOps,
31    /// Audits for security vulnerabilities.
32    SecurityAuditor,
33    /// Writes documentation.
34    Documenter,
35}
36
37impl fmt::Display for DevRole {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        match self {
40            Self::Architect => write!(f, "Architect"),
41            Self::Implementer => write!(f, "Implementer"),
42            Self::Tester => write!(f, "Tester"),
43            Self::Reviewer => write!(f, "Reviewer"),
44            Self::Debugger => write!(f, "Debugger"),
45            Self::DevOps => write!(f, "DevOps"),
46            Self::SecurityAuditor => write!(f, "SecurityAuditor"),
47            Self::Documenter => write!(f, "Documenter"),
48        }
49    }
50}
51
52/// A development workflow template.
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
54#[serde(rename_all = "snake_case")]
55pub enum DevWorkflow {
56    /// Full feature implementation: plan -> code -> test -> review.
57    ImplementFeature,
58    /// Bug fix: diagnose -> fix -> test -> review.
59    FixBug,
60    /// Code refactoring: analyze -> refactor -> test -> review.
61    Refactor,
62    /// Add test coverage: analyze -> write tests -> verify.
63    AddTests,
64    /// Security audit: scan -> report -> remediate -> verify.
65    SecurityAudit,
66    /// Code review: review -> feedback -> iterate.
67    CodeReview,
68    /// Performance optimization: profile -> optimize -> benchmark -> review.
69    Optimize,
70    /// Documentation: analyze -> write -> review.
71    WriteDocumentation,
72}
73
74impl fmt::Display for DevWorkflow {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        match self {
77            Self::ImplementFeature => write!(f, "Implement Feature"),
78            Self::FixBug => write!(f, "Fix Bug"),
79            Self::Refactor => write!(f, "Refactor"),
80            Self::AddTests => write!(f, "Add Tests"),
81            Self::SecurityAudit => write!(f, "Security Audit"),
82            Self::CodeReview => write!(f, "Code Review"),
83            Self::Optimize => write!(f, "Optimize"),
84            Self::WriteDocumentation => write!(f, "Write Documentation"),
85        }
86    }
87}
88
89/// All available workflow variants.
90const ALL_WORKFLOWS: [DevWorkflow; 8] = [
91    DevWorkflow::ImplementFeature,
92    DevWorkflow::FixBug,
93    DevWorkflow::Refactor,
94    DevWorkflow::AddTests,
95    DevWorkflow::SecurityAudit,
96    DevWorkflow::CodeReview,
97    DevWorkflow::Optimize,
98    DevWorkflow::WriteDocumentation,
99];
100
101/// A step in a workflow with role assignment and handoff rules.
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct WorkflowStep {
104    /// Step number (1-based).
105    pub order: usize,
106    /// Which role executes this step.
107    pub role: DevRole,
108    /// What this step does.
109    pub action: String,
110    /// Detailed instructions for the agent.
111    pub instructions: String,
112    /// What the agent should produce (input for next step).
113    pub expected_output: String,
114    /// Quality gate: minimum conditions to proceed.
115    pub gate: Option<QualityGate>,
116    /// Whether this step can be retried on failure.
117    pub retryable: bool,
118    /// Maximum retries.
119    pub max_retries: usize,
120}
121
122/// Quality gate that must pass before proceeding.
123#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct QualityGate {
125    /// Human-readable description of the gate.
126    pub description: String,
127    /// Type of check.
128    pub check_type: GateCheck,
129}
130
131/// The type of quality check for a gate.
132#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
133#[serde(rename_all = "snake_case")]
134pub enum GateCheck {
135    /// All tests must pass.
136    TestsPass,
137    /// Code review score must be above threshold (0-100).
138    ReviewScore {
139        /// Minimum acceptable score.
140        min_score: u32,
141    },
142    /// No security findings above a severity.
143    NoSecurityFindings {
144        /// Maximum acceptable severity (e.g. "low", "medium", "high", "critical").
145        max_severity: String,
146    },
147    /// Code compiles without errors.
148    CompileSuccess,
149    /// Custom check description.
150    Custom {
151        /// Description of the custom check.
152        check: String,
153    },
154}
155
156/// Configuration for a development team.
157#[derive(Debug, Clone, Serialize, Deserialize)]
158pub struct DevTeamConfig {
159    /// Team name.
160    pub name: String,
161    /// Roles present in the team.
162    pub roles: Vec<DevRole>,
163    /// Model tier preference per role.
164    pub role_models: Vec<(DevRole, String)>,
165    /// Maximum concurrent steps.
166    pub max_parallel: usize,
167    /// Whether to enforce quality gates.
168    pub enforce_gates: bool,
169    /// Maximum total iterations across all workflow steps.
170    pub max_iterations: usize,
171}
172
173/// Result of running a workflow.
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct WorkflowResult {
176    /// The workflow that was executed.
177    pub workflow: DevWorkflow,
178    /// Final status of the workflow.
179    pub status: WorkflowStatus,
180    /// Number of steps completed.
181    pub steps_completed: usize,
182    /// Total number of steps in the workflow.
183    pub steps_total: usize,
184    /// Artifacts produced by the workflow.
185    pub artifacts: Vec<WorkflowArtifact>,
186    /// Quality scores collected during execution (label, score).
187    pub quality_scores: Vec<(String, f32)>,
188    /// Human-readable notes about the execution.
189    pub notes: Vec<String>,
190}
191
192/// Status of a workflow execution.
193#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
194#[serde(rename_all = "snake_case")]
195pub enum WorkflowStatus {
196    /// Workflow completed successfully.
197    Completed,
198    /// Workflow failed at a specific step.
199    Failed {
200        /// Step number where the failure occurred.
201        step: usize,
202        /// Reason for the failure.
203        reason: String,
204    },
205    /// Workflow blocked by a quality gate.
206    GateBlocked {
207        /// Step number where the gate blocked progress.
208        step: usize,
209        /// Description of the gate that blocked.
210        gate: String,
211    },
212    /// Workflow was cancelled.
213    Cancelled,
214}
215
216/// An artifact produced during a workflow step.
217#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct WorkflowArtifact {
219    /// Name of the artifact.
220    pub name: String,
221    /// Type of artifact.
222    pub artifact_type: ArtifactType,
223    /// Content of the artifact.
224    pub content: String,
225}
226
227/// The type of artifact produced by a workflow step.
228#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
229#[serde(rename_all = "snake_case")]
230pub enum ArtifactType {
231    /// Architecture or implementation plan.
232    Plan,
233    /// Source code.
234    Code,
235    /// Test execution results.
236    TestResults,
237    /// Code review report.
238    ReviewReport,
239    /// Security audit report.
240    SecurityReport,
241    /// Written documentation.
242    Documentation,
243    /// Code diff.
244    Diff,
245}
246
247/// The development team orchestrator.
248///
249/// Coordinates a team of agents with specific roles through predefined
250/// workflows. Each workflow defines a sequence of steps with quality gates
251/// and handoff rules between agents.
252#[derive(Debug, Clone)]
253pub struct DevTeam {
254    config: DevTeamConfig,
255}
256
257impl DevTeam {
258    /// Create a default full-stack development team with all roles.
259    pub fn full_stack() -> Self {
260        Self {
261            config: DevTeamConfig {
262                name: "Full-Stack Team".to_string(),
263                roles: vec![
264                    DevRole::Architect,
265                    DevRole::Implementer,
266                    DevRole::Tester,
267                    DevRole::Reviewer,
268                    DevRole::Debugger,
269                    DevRole::DevOps,
270                    DevRole::SecurityAuditor,
271                    DevRole::Documenter,
272                ],
273                role_models: default_role_models(),
274                max_parallel: 3,
275                enforce_gates: true,
276                max_iterations: 50,
277            },
278        }
279    }
280
281    /// Create a minimal team (implementer + tester).
282    pub fn minimal() -> Self {
283        Self {
284            config: DevTeamConfig {
285                name: "Minimal Team".to_string(),
286                roles: vec![DevRole::Implementer, DevRole::Tester],
287                role_models: vec![
288                    (DevRole::Implementer, "balanced".to_string()),
289                    (DevRole::Tester, "balanced".to_string()),
290                ],
291                max_parallel: 1,
292                enforce_gates: false,
293                max_iterations: 20,
294            },
295        }
296    }
297
298    /// Create a security-focused team.
299    pub fn security_team() -> Self {
300        Self {
301            config: DevTeamConfig {
302                name: "Security Team".to_string(),
303                roles: vec![
304                    DevRole::SecurityAuditor,
305                    DevRole::Implementer,
306                    DevRole::Reviewer,
307                    DevRole::Tester,
308                ],
309                role_models: vec![
310                    (DevRole::SecurityAuditor, "powerful".to_string()),
311                    (DevRole::Implementer, "balanced".to_string()),
312                    (DevRole::Reviewer, "powerful".to_string()),
313                    (DevRole::Tester, "balanced".to_string()),
314                ],
315                max_parallel: 2,
316                enforce_gates: true,
317                max_iterations: 40,
318            },
319        }
320    }
321
322    /// Create with custom config.
323    pub fn with_config(config: DevTeamConfig) -> Self {
324        Self { config }
325    }
326
327    /// Get the workflow steps for a given workflow type.
328    pub fn workflow_steps(&self, workflow: DevWorkflow) -> Vec<WorkflowStep> {
329        match workflow {
330            DevWorkflow::ImplementFeature => build_implement_feature_steps(),
331            DevWorkflow::FixBug => build_fix_bug_steps(),
332            DevWorkflow::Refactor => build_refactor_steps(),
333            DevWorkflow::AddTests => build_add_tests_steps(),
334            DevWorkflow::SecurityAudit => build_security_audit_steps(),
335            DevWorkflow::CodeReview => build_code_review_steps(),
336            DevWorkflow::Optimize => build_optimize_steps(),
337            DevWorkflow::WriteDocumentation => build_write_documentation_steps(),
338        }
339    }
340
341    /// Get the roles needed for a workflow.
342    pub fn required_roles(&self, workflow: DevWorkflow) -> Vec<DevRole> {
343        let steps = self.workflow_steps(workflow);
344        let mut roles: Vec<DevRole> = Vec::new();
345        for step in &steps {
346            if !roles.contains(&step.role) {
347                roles.push(step.role);
348            }
349        }
350        roles
351    }
352
353    /// Check if the team has all required roles for a workflow.
354    pub fn can_run_workflow(&self, workflow: DevWorkflow) -> bool {
355        let required = self.required_roles(workflow);
356        required.iter().all(|r| self.config.roles.contains(r))
357    }
358
359    /// Get the model tier recommendation for a role.
360    pub fn model_for_role(&self, role: DevRole) -> String {
361        self.config
362            .role_models
363            .iter()
364            .find(|(r, _)| *r == role)
365            .map(|(_, m)| m.clone())
366            .unwrap_or_else(|| default_model_tier(role).to_string())
367    }
368
369    /// Validate a workflow result against quality gates.
370    ///
371    /// Returns `true` if the step's gate conditions are satisfied by the
372    /// provided artifacts, or if the step has no gate. When gates are not
373    /// enforced in the team config, always returns `true`.
374    pub fn validate_gates(
375        &self,
376        workflow: DevWorkflow,
377        step: usize,
378        artifacts: &[WorkflowArtifact],
379    ) -> bool {
380        if !self.config.enforce_gates {
381            return true;
382        }
383
384        let steps = self.workflow_steps(workflow);
385        let target_step = steps.iter().find(|s| s.order == step);
386
387        let target_step = match target_step {
388            Some(s) => s,
389            None => return false,
390        };
391
392        let gate = match &target_step.gate {
393            Some(g) => g,
394            None => return true,
395        };
396
397        match &gate.check_type {
398            GateCheck::TestsPass => artifacts
399                .iter()
400                .any(|a| a.artifact_type == ArtifactType::TestResults),
401            GateCheck::ReviewScore { min_score } => {
402                // A review report artifact must exist.
403                // In a real implementation, we'd parse the score from the content.
404                // Here we check that a review report exists and that min_score
405                // is within the valid range.
406                *min_score <= 100
407                    && artifacts
408                        .iter()
409                        .any(|a| a.artifact_type == ArtifactType::ReviewReport)
410            }
411            GateCheck::NoSecurityFindings { .. } => artifacts
412                .iter()
413                .any(|a| a.artifact_type == ArtifactType::SecurityReport),
414            GateCheck::CompileSuccess => artifacts
415                .iter()
416                .any(|a| a.artifact_type == ArtifactType::Code),
417            GateCheck::Custom { .. } => {
418                // Custom gates pass if any artifact is present.
419                !artifacts.is_empty()
420            }
421        }
422    }
423
424    /// Generate the system prompt for an agent in a specific role.
425    pub fn role_system_prompt(&self, role: DevRole) -> String {
426        match role {
427            DevRole::Architect => "You are a senior software architect. \
428                Analyze requirements, decompose into tasks, identify dependencies, \
429                estimate effort, and assess risk. Produce detailed implementation \
430                plans with clear step-by-step instructions. Focus on modularity, \
431                scalability, and maintainability."
432                .to_string(),
433            DevRole::Implementer => "You are a senior software engineer. \
434                Write clean, efficient, well-tested code. Follow existing \
435                conventions and project patterns. Minimize changes to reduce \
436                risk. Never introduce security vulnerabilities. Use proper error \
437                handling and avoid panics in production code."
438                .to_string(),
439            DevRole::Tester => "You are a senior QA engineer. Write comprehensive \
440                tests covering happy paths, edge cases, error conditions, and \
441                boundary values. Use descriptive test names following the pattern \
442                test_<function>_<scenario>. Ensure tests are deterministic, fast, \
443                and independent of each other."
444                .to_string(),
445            DevRole::Reviewer => "You are a code reviewer. Evaluate code across \
446                correctness, security, performance, style, and test coverage. \
447                Provide specific, actionable feedback with line references. Score \
448                the review on a 0-100 scale. Flag blocking issues that must be \
449                addressed before merging."
450                .to_string(),
451            DevRole::Debugger => "You are a senior debugger and diagnostician. \
452                Reproduce bugs systematically, identify root causes through \
453                careful analysis, and propose minimal targeted fixes. Document \
454                the investigation process and findings clearly. Always verify \
455                that proposed fixes address the root cause, not just symptoms."
456                .to_string(),
457            DevRole::DevOps => "You are a DevOps engineer. Handle CI/CD pipelines, \
458                deployment configurations, infrastructure as code, and operational \
459                tooling. Follow best practices for reproducibility, security \
460                hardening, and monitoring. Ensure rollback safety."
461                .to_string(),
462            DevRole::SecurityAuditor => "You are a security auditor. Scan code \
463                for vulnerabilities including OWASP Top 10, insecure dependencies, \
464                secrets exposure, improper access controls, and cryptographic \
465                weaknesses. Classify findings by severity (critical, high, medium, \
466                low, informational). Provide actionable remediation guidance."
467                .to_string(),
468            DevRole::Documenter => "You are a technical writer. Write clear, \
469                accurate, and comprehensive documentation. Include code examples, \
470                API references, usage patterns, and architecture overviews. Follow \
471                the project's existing documentation style and conventions."
472                .to_string(),
473        }
474    }
475
476    /// Get the handoff message between steps (what to pass from step N to N+1).
477    pub fn handoff_message(
478        &self,
479        from_step: &WorkflowStep,
480        artifacts: &[WorkflowArtifact],
481    ) -> String {
482        let artifact_summary: Vec<String> = artifacts
483            .iter()
484            .map(|a| format!("[{}] {}", a.name, truncate_content(&a.content, 200)))
485            .collect();
486
487        format!(
488            "Handoff from Step {} ({}, {}): {}\n\nArtifacts produced:\n{}",
489            from_step.order,
490            from_step.role,
491            from_step.action,
492            from_step.expected_output,
493            if artifact_summary.is_empty() {
494                "  (none)".to_string()
495            } else {
496                artifact_summary
497                    .iter()
498                    .map(|s| format!("  - {s}"))
499                    .collect::<Vec<_>>()
500                    .join("\n")
501            }
502        )
503    }
504
505    /// Get all available workflows.
506    pub fn available_workflows(&self) -> Vec<DevWorkflow> {
507        ALL_WORKFLOWS.to_vec()
508    }
509
510    /// Describe a workflow in human-readable form.
511    pub fn describe_workflow(&self, workflow: DevWorkflow) -> String {
512        let steps = self.workflow_steps(workflow);
513        let step_descriptions: Vec<String> = steps
514            .iter()
515            .map(|s| {
516                let gate_info = s
517                    .gate
518                    .as_ref()
519                    .map(|g| format!(" [Gate: {}]", g.description))
520                    .unwrap_or_default();
521                format!(
522                    "  {}. {} ({}): {}{}",
523                    s.order, s.role, s.action, s.expected_output, gate_info
524                )
525            })
526            .collect();
527
528        format!(
529            "Workflow: {workflow}\nSteps ({}):\n{}",
530            steps.len(),
531            step_descriptions.join("\n")
532        )
533    }
534
535    /// Get team summary.
536    pub fn summary(&self) -> String {
537        let roles: Vec<String> = self
538            .config
539            .roles
540            .iter()
541            .map(std::string::ToString::to_string)
542            .collect();
543        let runnable: Vec<String> = ALL_WORKFLOWS
544            .iter()
545            .filter(|w| self.can_run_workflow(**w))
546            .map(std::string::ToString::to_string)
547            .collect();
548
549        format!(
550            "Team: {}\nRoles ({}): {}\nMax parallel: {}\nEnforce gates: {}\nMax iterations: {}\nRunnable workflows ({}): {}",
551            self.config.name,
552            self.config.roles.len(),
553            roles.join(", "),
554            self.config.max_parallel,
555            self.config.enforce_gates,
556            self.config.max_iterations,
557            runnable.len(),
558            runnable.join(", "),
559        )
560    }
561}
562
563// ---------------------------------------------------------------------------
564// Private helpers
565// ---------------------------------------------------------------------------
566
567/// Truncate content to a maximum length, appending "..." if truncated.
568fn truncate_content(content: &str, max_len: usize) -> String {
569    if content.len() <= max_len {
570        content.to_string()
571    } else {
572        let truncated: String = content.chars().take(max_len).collect();
573        format!("{truncated}...")
574    }
575}
576
577/// Default model tier for each role.
578fn default_model_tier(role: DevRole) -> &'static str {
579    match role {
580        DevRole::Architect => "powerful",
581        DevRole::Implementer => "balanced",
582        DevRole::Tester => "balanced",
583        DevRole::Reviewer => "powerful",
584        DevRole::Debugger => "powerful",
585        DevRole::DevOps => "fast",
586        DevRole::SecurityAuditor => "powerful",
587        DevRole::Documenter => "fast",
588    }
589}
590
591/// Default role-to-model-tier mapping for all roles.
592fn default_role_models() -> Vec<(DevRole, String)> {
593    vec![
594        (DevRole::Architect, "powerful".to_string()),
595        (DevRole::Implementer, "balanced".to_string()),
596        (DevRole::Tester, "balanced".to_string()),
597        (DevRole::Reviewer, "powerful".to_string()),
598        (DevRole::Debugger, "powerful".to_string()),
599        (DevRole::DevOps, "fast".to_string()),
600        (DevRole::SecurityAuditor, "powerful".to_string()),
601        (DevRole::Documenter, "fast".to_string()),
602    ]
603}
604
605// ---------------------------------------------------------------------------
606// Workflow step builders
607// ---------------------------------------------------------------------------
608
609/// Build steps for the ImplementFeature workflow.
610fn build_implement_feature_steps() -> Vec<WorkflowStep> {
611    vec![
612        WorkflowStep {
613            order: 1,
614            role: DevRole::Architect,
615            action: "Analyze requirements and create implementation plan".to_string(),
616            instructions: "Review the feature requirements thoroughly. Break them down \
617                into concrete implementation tasks with clear acceptance criteria. \
618                Identify dependencies between tasks, estimate effort for each, and \
619                assess technical risks. Produce a detailed plan with step-by-step \
620                instructions for the implementer."
621                .to_string(),
622            expected_output:
623                "Detailed implementation plan with tasks, dependencies, and risk assessment"
624                    .to_string(),
625            gate: Some(QualityGate {
626                description: "Implementation plan produced".to_string(),
627                check_type: GateCheck::Custom {
628                    check: "Plan document exists and contains task breakdown".to_string(),
629                },
630            }),
631            retryable: true,
632            max_retries: 2,
633        },
634        WorkflowStep {
635            order: 2,
636            role: DevRole::Implementer,
637            action: "Write production code following the plan".to_string(),
638            instructions: "Implement the feature following the architect's plan. \
639                Write clean, idiomatic code that follows project conventions. \
640                Handle errors properly, avoid panics, and ensure the code compiles \
641                without warnings."
642                .to_string(),
643            expected_output: "Production code that compiles and implements the planned feature"
644                .to_string(),
645            gate: Some(QualityGate {
646                description: "Code compiles successfully".to_string(),
647                check_type: GateCheck::CompileSuccess,
648            }),
649            retryable: true,
650            max_retries: 3,
651        },
652        WorkflowStep {
653            order: 3,
654            role: DevRole::Tester,
655            action: "Write and run tests for the new feature".to_string(),
656            instructions: "Write comprehensive tests for the implemented feature. \
657                Cover happy paths, edge cases, error conditions, and boundary values. \
658                Ensure tests are deterministic and independent. Run all tests and \
659                verify they pass."
660                .to_string(),
661            expected_output: "Test suite with passing results and coverage report".to_string(),
662            gate: Some(QualityGate {
663                description: "All tests pass".to_string(),
664                check_type: GateCheck::TestsPass,
665            }),
666            retryable: true,
667            max_retries: 3,
668        },
669        WorkflowStep {
670            order: 4,
671            role: DevRole::Reviewer,
672            action: "Review code for quality, security, and style".to_string(),
673            instructions: "Review the implementation and tests for correctness, \
674                security vulnerabilities, performance issues, coding style, and \
675                test coverage. Provide specific, actionable feedback with line \
676                references. Score the review on a 0-100 scale."
677                .to_string(),
678            expected_output: "Review report with score, findings, and recommendations".to_string(),
679            gate: Some(QualityGate {
680                description: "Review score >= 70".to_string(),
681                check_type: GateCheck::ReviewScore { min_score: 70 },
682            }),
683            retryable: false,
684            max_retries: 0,
685        },
686        WorkflowStep {
687            order: 5,
688            role: DevRole::Documenter,
689            action: "Update documentation for the new feature".to_string(),
690            instructions: "Write or update documentation for the newly implemented \
691                feature. Include API references, usage examples, and any \
692                configuration changes. Follow the project's documentation style."
693                .to_string(),
694            expected_output: "Updated documentation covering the new feature".to_string(),
695            gate: None,
696            retryable: true,
697            max_retries: 1,
698        },
699    ]
700}
701
702/// Build steps for the FixBug workflow.
703fn build_fix_bug_steps() -> Vec<WorkflowStep> {
704    vec![
705        WorkflowStep {
706            order: 1,
707            role: DevRole::Debugger,
708            action: "Reproduce and diagnose the root cause".to_string(),
709            instructions: "Reproduce the bug systematically. Analyze logs, stack traces, \
710                and code paths to identify the root cause. Document the reproduction \
711                steps and root cause analysis clearly."
712                .to_string(),
713            expected_output: "Root cause analysis with reproduction steps".to_string(),
714            gate: Some(QualityGate {
715                description: "Root cause identified".to_string(),
716                check_type: GateCheck::Custom {
717                    check: "Root cause analysis document produced".to_string(),
718                },
719            }),
720            retryable: true,
721            max_retries: 2,
722        },
723        WorkflowStep {
724            order: 2,
725            role: DevRole::Implementer,
726            action: "Apply the fix with minimal changes".to_string(),
727            instructions: "Implement a targeted fix based on the root cause analysis. \
728                Minimize code changes to reduce regression risk. Ensure the fix \
729                addresses the root cause, not just symptoms. The code must compile \
730                without errors or warnings."
731                .to_string(),
732            expected_output: "Bug fix code that compiles successfully".to_string(),
733            gate: Some(QualityGate {
734                description: "Code compiles successfully".to_string(),
735                check_type: GateCheck::CompileSuccess,
736            }),
737            retryable: true,
738            max_retries: 3,
739        },
740        WorkflowStep {
741            order: 3,
742            role: DevRole::Tester,
743            action: "Write regression test and verify fix".to_string(),
744            instructions: "Write a regression test that reproduces the original bug \
745                and verifies the fix. Run the full test suite to check for regressions. \
746                The regression test must fail without the fix and pass with it."
747                .to_string(),
748            expected_output: "Regression test and full test suite results".to_string(),
749            gate: Some(QualityGate {
750                description: "All tests pass".to_string(),
751                check_type: GateCheck::TestsPass,
752            }),
753            retryable: true,
754            max_retries: 3,
755        },
756        WorkflowStep {
757            order: 4,
758            role: DevRole::Reviewer,
759            action: "Review the fix for correctness and side effects".to_string(),
760            instructions: "Review the bug fix for correctness, potential side effects, \
761                and regression risk. Verify the fix addresses the root cause. Check \
762                that the regression test is adequate. Score on a 0-100 scale."
763                .to_string(),
764            expected_output: "Review report with assessment of fix quality".to_string(),
765            gate: Some(QualityGate {
766                description: "Review score >= 70".to_string(),
767                check_type: GateCheck::ReviewScore { min_score: 70 },
768            }),
769            retryable: false,
770            max_retries: 0,
771        },
772    ]
773}
774
775/// Build steps for the Refactor workflow.
776fn build_refactor_steps() -> Vec<WorkflowStep> {
777    vec![
778        WorkflowStep {
779            order: 1,
780            role: DevRole::Architect,
781            action: "Analyze code structure and plan refactoring approach".to_string(),
782            instructions: "Analyze the current code structure and identify areas for \
783                improvement. Design the refactoring approach with clear goals \
784                (readability, performance, modularity). Ensure the plan preserves \
785                existing behavior."
786                .to_string(),
787            expected_output: "Refactoring plan with goals and approach".to_string(),
788            gate: Some(QualityGate {
789                description: "Refactoring plan produced".to_string(),
790                check_type: GateCheck::Custom {
791                    check: "Plan document exists with refactoring strategy".to_string(),
792                },
793            }),
794            retryable: true,
795            max_retries: 2,
796        },
797        WorkflowStep {
798            order: 2,
799            role: DevRole::Implementer,
800            action: "Apply refactoring changes".to_string(),
801            instructions: "Apply the planned refactoring changes. Make incremental, \
802                verifiable changes. Preserve all existing behavior. The code must \
803                compile without errors or warnings."
804                .to_string(),
805            expected_output: "Refactored code that compiles successfully".to_string(),
806            gate: Some(QualityGate {
807                description: "Code compiles successfully".to_string(),
808                check_type: GateCheck::CompileSuccess,
809            }),
810            retryable: true,
811            max_retries: 3,
812        },
813        WorkflowStep {
814            order: 3,
815            role: DevRole::Tester,
816            action: "Run existing tests and verify no regressions".to_string(),
817            instructions: "Run the full test suite to verify the refactoring did not \
818                introduce any regressions. All existing tests must continue to pass. \
819                Add tests for any new code paths introduced by the refactoring."
820                .to_string(),
821            expected_output: "Test results showing no regressions".to_string(),
822            gate: Some(QualityGate {
823                description: "All tests pass".to_string(),
824                check_type: GateCheck::TestsPass,
825            }),
826            retryable: true,
827            max_retries: 3,
828        },
829        WorkflowStep {
830            order: 4,
831            role: DevRole::Reviewer,
832            action: "Review refactoring for improved design quality".to_string(),
833            instructions: "Review the refactored code for design improvement, \
834                readability, and correctness. Verify behavior is preserved. \
835                Assess whether the refactoring achieved its stated goals. \
836                Score on a 0-100 scale."
837                .to_string(),
838            expected_output: "Review report with design quality assessment".to_string(),
839            gate: Some(QualityGate {
840                description: "Review score >= 70".to_string(),
841                check_type: GateCheck::ReviewScore { min_score: 70 },
842            }),
843            retryable: false,
844            max_retries: 0,
845        },
846    ]
847}
848
849/// Build steps for the AddTests workflow.
850fn build_add_tests_steps() -> Vec<WorkflowStep> {
851    vec![
852        WorkflowStep {
853            order: 1,
854            role: DevRole::Tester,
855            action: "Analyze code and identify untested paths".to_string(),
856            instructions: "Analyze the codebase to identify untested code paths, \
857                functions, and edge cases. Prioritize critical paths and security- \
858                sensitive code. Produce a test plan with identified gaps."
859                .to_string(),
860            expected_output: "Test plan identifying coverage gaps and priorities".to_string(),
861            gate: None,
862            retryable: true,
863            max_retries: 1,
864        },
865        WorkflowStep {
866            order: 2,
867            role: DevRole::Tester,
868            action: "Write comprehensive tests".to_string(),
869            instructions: "Write tests to fill the identified coverage gaps. Include \
870                unit tests, integration tests, and edge case tests. Use descriptive \
871                test names and follow project conventions. All tests must pass."
872                .to_string(),
873            expected_output: "New test suite with passing results".to_string(),
874            gate: Some(QualityGate {
875                description: "All tests pass".to_string(),
876                check_type: GateCheck::TestsPass,
877            }),
878            retryable: true,
879            max_retries: 3,
880        },
881        WorkflowStep {
882            order: 3,
883            role: DevRole::Reviewer,
884            action: "Review test quality and coverage".to_string(),
885            instructions: "Review the new tests for quality, completeness, and \
886                correctness. Verify tests actually test meaningful behavior and are \
887                not trivial. Assess coverage improvement. Score on a 0-100 scale."
888                .to_string(),
889            expected_output: "Review report with test quality assessment".to_string(),
890            gate: Some(QualityGate {
891                description: "Review score >= 60".to_string(),
892                check_type: GateCheck::ReviewScore { min_score: 60 },
893            }),
894            retryable: false,
895            max_retries: 0,
896        },
897    ]
898}
899
900/// Build steps for the SecurityAudit workflow.
901fn build_security_audit_steps() -> Vec<WorkflowStep> {
902    vec![
903        WorkflowStep {
904            order: 1,
905            role: DevRole::SecurityAuditor,
906            action: "Scan code for security vulnerabilities".to_string(),
907            instructions: "Perform a comprehensive security scan of the codebase. \
908                Check for OWASP Top 10 vulnerabilities, insecure dependencies, \
909                secrets exposure, improper access controls, and cryptographic \
910                weaknesses. Classify findings by severity."
911                .to_string(),
912            expected_output: "Security scan results with classified findings".to_string(),
913            gate: Some(QualityGate {
914                description: "Security scan completed".to_string(),
915                check_type: GateCheck::Custom {
916                    check: "Security scan report produced with findings classified".to_string(),
917                },
918            }),
919            retryable: true,
920            max_retries: 2,
921        },
922        WorkflowStep {
923            order: 2,
924            role: DevRole::SecurityAuditor,
925            action: "Generate detailed security report with findings".to_string(),
926            instructions: "Compile a detailed security audit report. Include all \
927                findings with severity classification, affected code locations, \
928                potential impact, and recommended remediations. Prioritize \
929                findings by risk."
930                .to_string(),
931            expected_output: "Detailed security audit report".to_string(),
932            gate: None,
933            retryable: true,
934            max_retries: 1,
935        },
936        WorkflowStep {
937            order: 3,
938            role: DevRole::Implementer,
939            action: "Apply security remediations".to_string(),
940            instructions: "Implement fixes for the security findings identified in \
941                the audit report. Prioritize critical and high severity findings. \
942                Follow security best practices and the auditor's recommendations. \
943                The code must compile without errors."
944                .to_string(),
945            expected_output: "Remediated code that compiles successfully".to_string(),
946            gate: Some(QualityGate {
947                description: "Code compiles successfully".to_string(),
948                check_type: GateCheck::CompileSuccess,
949            }),
950            retryable: true,
951            max_retries: 3,
952        },
953        WorkflowStep {
954            order: 4,
955            role: DevRole::SecurityAuditor,
956            action: "Verify remediations and re-scan".to_string(),
957            instructions: "Re-scan the remediated code to verify that security fixes \
958                are effective. Confirm that no new vulnerabilities were introduced. \
959                Verify there are no remaining critical or high severity findings."
960                .to_string(),
961            expected_output: "Verification report confirming remediations".to_string(),
962            gate: Some(QualityGate {
963                description: "No critical security findings".to_string(),
964                check_type: GateCheck::NoSecurityFindings {
965                    max_severity: "high".to_string(),
966                },
967            }),
968            retryable: true,
969            max_retries: 2,
970        },
971    ]
972}
973
974/// Build steps for the CodeReview workflow.
975fn build_code_review_steps() -> Vec<WorkflowStep> {
976    vec![
977        WorkflowStep {
978            order: 1,
979            role: DevRole::Reviewer,
980            action: "Perform detailed code review across all dimensions".to_string(),
981            instructions: "Review the code across correctness, security, performance, \
982                readability, maintainability, and test coverage. Provide specific, \
983                actionable feedback with file and line references. Identify blocking \
984                and non-blocking issues."
985                .to_string(),
986            expected_output: "Detailed code review with categorized feedback".to_string(),
987            gate: None,
988            retryable: true,
989            max_retries: 1,
990        },
991        WorkflowStep {
992            order: 2,
993            role: DevRole::Implementer,
994            action: "Address review feedback".to_string(),
995            instructions: "Address all blocking issues from the code review. Apply \
996                non-blocking suggestions where appropriate. Explain any feedback \
997                that was intentionally not addressed. The code must compile."
998                .to_string(),
999            expected_output: "Updated code addressing review feedback".to_string(),
1000            gate: Some(QualityGate {
1001                description: "Code compiles successfully".to_string(),
1002                check_type: GateCheck::CompileSuccess,
1003            }),
1004            retryable: true,
1005            max_retries: 3,
1006        },
1007        WorkflowStep {
1008            order: 3,
1009            role: DevRole::Reviewer,
1010            action: "Verify changes address all feedback".to_string(),
1011            instructions: "Re-review the updated code to verify all blocking feedback \
1012                has been addressed. Check that fixes are correct and no new issues \
1013                were introduced. Score on a 0-100 scale."
1014                .to_string(),
1015            expected_output: "Final review report with approval status".to_string(),
1016            gate: Some(QualityGate {
1017                description: "Review score >= 80".to_string(),
1018                check_type: GateCheck::ReviewScore { min_score: 80 },
1019            }),
1020            retryable: false,
1021            max_retries: 0,
1022        },
1023    ]
1024}
1025
1026/// Build steps for the Optimize workflow.
1027fn build_optimize_steps() -> Vec<WorkflowStep> {
1028    vec![
1029        WorkflowStep {
1030            order: 1,
1031            role: DevRole::Architect,
1032            action: "Profile and identify performance bottlenecks".to_string(),
1033            instructions: "Analyze the codebase to identify performance bottlenecks. \
1034                Profile critical paths, measure latencies, and identify hot spots. \
1035                Prioritize optimization targets by impact and effort."
1036                .to_string(),
1037            expected_output: "Performance analysis with identified bottlenecks".to_string(),
1038            gate: None,
1039            retryable: true,
1040            max_retries: 1,
1041        },
1042        WorkflowStep {
1043            order: 2,
1044            role: DevRole::Implementer,
1045            action: "Apply optimizations".to_string(),
1046            instructions: "Implement performance optimizations for the identified \
1047                bottlenecks. Use algorithmic improvements, caching, batching, or \
1048                concurrency as appropriate. Maintain code readability and correctness. \
1049                The code must compile."
1050                .to_string(),
1051            expected_output: "Optimized code that compiles successfully".to_string(),
1052            gate: Some(QualityGate {
1053                description: "Code compiles successfully".to_string(),
1054                check_type: GateCheck::CompileSuccess,
1055            }),
1056            retryable: true,
1057            max_retries: 3,
1058        },
1059        WorkflowStep {
1060            order: 3,
1061            role: DevRole::Tester,
1062            action: "Run benchmarks and verify improvement".to_string(),
1063            instructions: "Run performance benchmarks comparing before and after the \
1064                optimization. Verify that the optimization improves performance \
1065                without introducing regressions. Run the full test suite."
1066                .to_string(),
1067            expected_output: "Benchmark results and test suite results".to_string(),
1068            gate: Some(QualityGate {
1069                description: "All tests pass".to_string(),
1070                check_type: GateCheck::TestsPass,
1071            }),
1072            retryable: true,
1073            max_retries: 2,
1074        },
1075        WorkflowStep {
1076            order: 4,
1077            role: DevRole::Reviewer,
1078            action: "Review optimizations for correctness".to_string(),
1079            instructions: "Review the optimization changes for correctness and \
1080                maintainability. Verify the performance improvement is real and \
1081                not a measurement artifact. Check for algorithmic correctness. \
1082                Score on a 0-100 scale."
1083                .to_string(),
1084            expected_output: "Review report assessing optimization quality".to_string(),
1085            gate: Some(QualityGate {
1086                description: "Review score >= 70".to_string(),
1087                check_type: GateCheck::ReviewScore { min_score: 70 },
1088            }),
1089            retryable: false,
1090            max_retries: 0,
1091        },
1092    ]
1093}
1094
1095/// Build steps for the WriteDocumentation workflow.
1096fn build_write_documentation_steps() -> Vec<WorkflowStep> {
1097    vec![
1098        WorkflowStep {
1099            order: 1,
1100            role: DevRole::Architect,
1101            action: "Analyze codebase and identify documentation gaps".to_string(),
1102            instructions: "Analyze the codebase structure, public APIs, and existing \
1103                documentation. Identify undocumented or poorly documented areas. \
1104                Prioritize documentation needs and produce an outline."
1105                .to_string(),
1106            expected_output: "Documentation gap analysis and outline".to_string(),
1107            gate: None,
1108            retryable: true,
1109            max_retries: 1,
1110        },
1111        WorkflowStep {
1112            order: 2,
1113            role: DevRole::Documenter,
1114            action: "Write comprehensive documentation".to_string(),
1115            instructions: "Write documentation following the outline. Include API \
1116                references, usage examples, architecture overviews, and getting \
1117                started guides. Use proper formatting and follow the project's \
1118                documentation style."
1119                .to_string(),
1120            expected_output: "Comprehensive documentation content".to_string(),
1121            gate: None,
1122            retryable: true,
1123            max_retries: 2,
1124        },
1125        WorkflowStep {
1126            order: 3,
1127            role: DevRole::Reviewer,
1128            action: "Review documentation for accuracy and completeness".to_string(),
1129            instructions: "Review the documentation for technical accuracy, \
1130                completeness, clarity, and consistency with the actual code. \
1131                Verify code examples compile and work correctly. Score on a \
1132                0-100 scale."
1133                .to_string(),
1134            expected_output: "Review report on documentation quality".to_string(),
1135            gate: Some(QualityGate {
1136                description: "Review score >= 60".to_string(),
1137                check_type: GateCheck::ReviewScore { min_score: 60 },
1138            }),
1139            retryable: false,
1140            max_retries: 0,
1141        },
1142    ]
1143}
1144
1145// ---------------------------------------------------------------------------
1146// Tests
1147// ---------------------------------------------------------------------------
1148
1149#[cfg(test)]
1150#[allow(clippy::unwrap_used, clippy::expect_used)]
1151mod tests {
1152    use super::*;
1153
1154    #[test]
1155    fn test_full_stack_team() {
1156        let team = DevTeam::full_stack();
1157        assert_eq!(team.config.name, "Full-Stack Team");
1158        assert_eq!(team.config.roles.len(), 8);
1159        assert!(team.config.enforce_gates);
1160        assert_eq!(team.config.max_parallel, 3);
1161
1162        // Every DevRole should be present
1163        assert!(team.config.roles.contains(&DevRole::Architect));
1164        assert!(team.config.roles.contains(&DevRole::Implementer));
1165        assert!(team.config.roles.contains(&DevRole::Tester));
1166        assert!(team.config.roles.contains(&DevRole::Reviewer));
1167        assert!(team.config.roles.contains(&DevRole::Debugger));
1168        assert!(team.config.roles.contains(&DevRole::DevOps));
1169        assert!(team.config.roles.contains(&DevRole::SecurityAuditor));
1170        assert!(team.config.roles.contains(&DevRole::Documenter));
1171    }
1172
1173    #[test]
1174    fn test_minimal_team() {
1175        let team = DevTeam::minimal();
1176        assert_eq!(team.config.name, "Minimal Team");
1177        assert_eq!(team.config.roles.len(), 2);
1178        assert!(team.config.roles.contains(&DevRole::Implementer));
1179        assert!(team.config.roles.contains(&DevRole::Tester));
1180        assert!(!team.config.enforce_gates);
1181        assert_eq!(team.config.max_parallel, 1);
1182    }
1183
1184    #[test]
1185    fn test_security_team() {
1186        let team = DevTeam::security_team();
1187        assert_eq!(team.config.name, "Security Team");
1188        assert!(team.config.roles.contains(&DevRole::SecurityAuditor));
1189        assert!(team.config.roles.contains(&DevRole::Implementer));
1190        assert!(team.config.roles.contains(&DevRole::Reviewer));
1191        assert!(team.config.roles.contains(&DevRole::Tester));
1192        assert!(team.config.enforce_gates);
1193    }
1194
1195    #[test]
1196    fn test_workflow_implement_feature() {
1197        let team = DevTeam::full_stack();
1198        let steps = team.workflow_steps(DevWorkflow::ImplementFeature);
1199        assert_eq!(steps.len(), 5);
1200        assert_eq!(steps[0].role, DevRole::Architect);
1201        assert_eq!(steps[1].role, DevRole::Implementer);
1202        assert_eq!(steps[2].role, DevRole::Tester);
1203        assert_eq!(steps[3].role, DevRole::Reviewer);
1204        assert_eq!(steps[4].role, DevRole::Documenter);
1205        // Last step has no gate
1206        assert!(steps[4].gate.is_none());
1207    }
1208
1209    #[test]
1210    fn test_workflow_fix_bug() {
1211        let team = DevTeam::full_stack();
1212        let steps = team.workflow_steps(DevWorkflow::FixBug);
1213        assert_eq!(steps.len(), 4);
1214        assert_eq!(steps[0].role, DevRole::Debugger);
1215        assert_eq!(steps[1].role, DevRole::Implementer);
1216        assert_eq!(steps[2].role, DevRole::Tester);
1217        assert_eq!(steps[3].role, DevRole::Reviewer);
1218    }
1219
1220    #[test]
1221    fn test_workflow_refactor() {
1222        let team = DevTeam::full_stack();
1223        let steps = team.workflow_steps(DevWorkflow::Refactor);
1224        assert_eq!(steps.len(), 4);
1225        assert_eq!(steps[0].role, DevRole::Architect);
1226        assert_eq!(steps[1].role, DevRole::Implementer);
1227        assert_eq!(steps[2].role, DevRole::Tester);
1228        assert_eq!(steps[3].role, DevRole::Reviewer);
1229    }
1230
1231    #[test]
1232    fn test_workflow_add_tests() {
1233        let team = DevTeam::full_stack();
1234        let steps = team.workflow_steps(DevWorkflow::AddTests);
1235        assert_eq!(steps.len(), 3);
1236        assert_eq!(steps[0].role, DevRole::Tester);
1237        assert_eq!(steps[1].role, DevRole::Tester);
1238        assert_eq!(steps[2].role, DevRole::Reviewer);
1239        // First step has no gate
1240        assert!(steps[0].gate.is_none());
1241    }
1242
1243    #[test]
1244    fn test_workflow_security_audit() {
1245        let team = DevTeam::full_stack();
1246        let steps = team.workflow_steps(DevWorkflow::SecurityAudit);
1247        assert_eq!(steps.len(), 4);
1248        assert_eq!(steps[0].role, DevRole::SecurityAuditor);
1249        assert_eq!(steps[1].role, DevRole::SecurityAuditor);
1250        assert_eq!(steps[2].role, DevRole::Implementer);
1251        assert_eq!(steps[3].role, DevRole::SecurityAuditor);
1252    }
1253
1254    #[test]
1255    fn test_workflow_code_review() {
1256        let team = DevTeam::full_stack();
1257        let steps = team.workflow_steps(DevWorkflow::CodeReview);
1258        assert_eq!(steps.len(), 3);
1259        assert_eq!(steps[0].role, DevRole::Reviewer);
1260        assert_eq!(steps[1].role, DevRole::Implementer);
1261        assert_eq!(steps[2].role, DevRole::Reviewer);
1262        // Final review gate requires score >= 80
1263        let gate = steps[2].gate.as_ref().unwrap();
1264        assert_eq!(gate.check_type, GateCheck::ReviewScore { min_score: 80 });
1265    }
1266
1267    #[test]
1268    fn test_workflow_optimize() {
1269        let team = DevTeam::full_stack();
1270        let steps = team.workflow_steps(DevWorkflow::Optimize);
1271        assert_eq!(steps.len(), 4);
1272        assert_eq!(steps[0].role, DevRole::Architect);
1273        assert_eq!(steps[1].role, DevRole::Implementer);
1274        assert_eq!(steps[2].role, DevRole::Tester);
1275        assert_eq!(steps[3].role, DevRole::Reviewer);
1276    }
1277
1278    #[test]
1279    fn test_workflow_write_docs() {
1280        let team = DevTeam::full_stack();
1281        let steps = team.workflow_steps(DevWorkflow::WriteDocumentation);
1282        assert_eq!(steps.len(), 3);
1283        assert_eq!(steps[0].role, DevRole::Architect);
1284        assert_eq!(steps[1].role, DevRole::Documenter);
1285        assert_eq!(steps[2].role, DevRole::Reviewer);
1286        // Review gate requires score >= 60
1287        let gate = steps[2].gate.as_ref().unwrap();
1288        assert_eq!(gate.check_type, GateCheck::ReviewScore { min_score: 60 });
1289    }
1290
1291    #[test]
1292    fn test_required_roles_feature() {
1293        let team = DevTeam::full_stack();
1294        let roles = team.required_roles(DevWorkflow::ImplementFeature);
1295        assert!(roles.contains(&DevRole::Architect));
1296        assert!(roles.contains(&DevRole::Implementer));
1297        assert!(roles.contains(&DevRole::Tester));
1298        assert!(roles.contains(&DevRole::Reviewer));
1299        assert!(roles.contains(&DevRole::Documenter));
1300        // No duplicates
1301        assert_eq!(roles.len(), 5);
1302    }
1303
1304    #[test]
1305    fn test_can_run_workflow_true() {
1306        let team = DevTeam::full_stack();
1307        assert!(team.can_run_workflow(DevWorkflow::ImplementFeature));
1308        assert!(team.can_run_workflow(DevWorkflow::FixBug));
1309        assert!(team.can_run_workflow(DevWorkflow::SecurityAudit));
1310    }
1311
1312    #[test]
1313    fn test_can_run_workflow_false() {
1314        let team = DevTeam::minimal();
1315        // Minimal team (Implementer + Tester) cannot run ImplementFeature
1316        // because it requires Architect, Reviewer, and Documenter
1317        assert!(!team.can_run_workflow(DevWorkflow::ImplementFeature));
1318        assert!(!team.can_run_workflow(DevWorkflow::FixBug));
1319        assert!(!team.can_run_workflow(DevWorkflow::SecurityAudit));
1320    }
1321
1322    #[test]
1323    fn test_model_for_role() {
1324        let team = DevTeam::full_stack();
1325        assert_eq!(team.model_for_role(DevRole::Architect), "powerful");
1326        assert_eq!(team.model_for_role(DevRole::Implementer), "balanced");
1327        assert_eq!(team.model_for_role(DevRole::Tester), "balanced");
1328        assert_eq!(team.model_for_role(DevRole::Reviewer), "powerful");
1329        assert_eq!(team.model_for_role(DevRole::Debugger), "powerful");
1330        assert_eq!(team.model_for_role(DevRole::DevOps), "fast");
1331        assert_eq!(team.model_for_role(DevRole::SecurityAuditor), "powerful");
1332        assert_eq!(team.model_for_role(DevRole::Documenter), "fast");
1333    }
1334
1335    #[test]
1336    fn test_role_system_prompt_not_empty() {
1337        let team = DevTeam::full_stack();
1338        let all_roles = [
1339            DevRole::Architect,
1340            DevRole::Implementer,
1341            DevRole::Tester,
1342            DevRole::Reviewer,
1343            DevRole::Debugger,
1344            DevRole::DevOps,
1345            DevRole::SecurityAuditor,
1346            DevRole::Documenter,
1347        ];
1348        for role in &all_roles {
1349            let prompt = team.role_system_prompt(*role);
1350            assert!(
1351                !prompt.is_empty(),
1352                "System prompt for {role} should not be empty"
1353            );
1354            assert!(
1355                prompt.len() > 50,
1356                "System prompt for {role} should be substantive"
1357            );
1358        }
1359    }
1360
1361    #[test]
1362    fn test_validate_gates_tests_pass() {
1363        let team = DevTeam::full_stack();
1364        let artifacts_with_tests = vec![WorkflowArtifact {
1365            name: "test_results".to_string(),
1366            artifact_type: ArtifactType::TestResults,
1367            content: "All 42 tests passed".to_string(),
1368        }];
1369        let artifacts_without = vec![WorkflowArtifact {
1370            name: "code".to_string(),
1371            artifact_type: ArtifactType::Code,
1372            content: "fn main() {}".to_string(),
1373        }];
1374
1375        // Step 3 of ImplementFeature has TestsPass gate
1376        assert!(team.validate_gates(DevWorkflow::ImplementFeature, 3, &artifacts_with_tests));
1377        assert!(!team.validate_gates(DevWorkflow::ImplementFeature, 3, &artifacts_without));
1378    }
1379
1380    #[test]
1381    fn test_validate_gates_review_score() {
1382        let team = DevTeam::full_stack();
1383        let artifacts_with_review = vec![WorkflowArtifact {
1384            name: "review".to_string(),
1385            artifact_type: ArtifactType::ReviewReport,
1386            content: "Score: 85/100. LGTM.".to_string(),
1387        }];
1388        let artifacts_without = vec![WorkflowArtifact {
1389            name: "code".to_string(),
1390            artifact_type: ArtifactType::Code,
1391            content: "fn main() {}".to_string(),
1392        }];
1393
1394        // Step 4 of ImplementFeature has ReviewScore { min_score: 70 } gate
1395        assert!(team.validate_gates(DevWorkflow::ImplementFeature, 4, &artifacts_with_review));
1396        assert!(!team.validate_gates(DevWorkflow::ImplementFeature, 4, &artifacts_without));
1397    }
1398
1399    #[test]
1400    fn test_describe_workflow() {
1401        let team = DevTeam::full_stack();
1402        let description = team.describe_workflow(DevWorkflow::ImplementFeature);
1403        assert!(description.contains("Implement Feature"));
1404        assert!(description.contains("Architect"));
1405        assert!(description.contains("Implementer"));
1406        assert!(description.contains("Tester"));
1407        assert!(description.contains("Reviewer"));
1408        assert!(description.contains("Documenter"));
1409        assert!(description.contains("Steps (5)"));
1410    }
1411
1412    #[test]
1413    fn test_available_workflows() {
1414        let team = DevTeam::full_stack();
1415        let workflows = team.available_workflows();
1416        assert_eq!(workflows.len(), 8);
1417        assert!(workflows.contains(&DevWorkflow::ImplementFeature));
1418        assert!(workflows.contains(&DevWorkflow::FixBug));
1419        assert!(workflows.contains(&DevWorkflow::Refactor));
1420        assert!(workflows.contains(&DevWorkflow::AddTests));
1421        assert!(workflows.contains(&DevWorkflow::SecurityAudit));
1422        assert!(workflows.contains(&DevWorkflow::CodeReview));
1423        assert!(workflows.contains(&DevWorkflow::Optimize));
1424        assert!(workflows.contains(&DevWorkflow::WriteDocumentation));
1425    }
1426
1427    #[test]
1428    fn test_team_summary() {
1429        let team = DevTeam::full_stack();
1430        let summary = team.summary();
1431        assert!(summary.contains("Full-Stack Team"));
1432        assert!(summary.contains("Roles (8)"));
1433        assert!(summary.contains("Architect"));
1434        assert!(summary.contains("Enforce gates: true"));
1435        assert!(summary.contains("Max parallel: 3"));
1436    }
1437
1438    #[test]
1439    fn test_handoff_message() {
1440        let team = DevTeam::full_stack();
1441        let steps = team.workflow_steps(DevWorkflow::ImplementFeature);
1442        let artifacts = vec![WorkflowArtifact {
1443            name: "implementation_plan".to_string(),
1444            artifact_type: ArtifactType::Plan,
1445            content: "1. Create module\n2. Add types\n3. Implement logic".to_string(),
1446        }];
1447
1448        let message = team.handoff_message(&steps[0], &artifacts);
1449        assert!(message.contains("Handoff from Step 1"));
1450        assert!(message.contains("Architect"));
1451        assert!(message.contains("implementation_plan"));
1452        assert!(message.contains("Create module"));
1453    }
1454
1455    #[test]
1456    fn test_workflow_step_ordering() {
1457        let team = DevTeam::full_stack();
1458        let all_workflows = team.available_workflows();
1459
1460        for workflow in &all_workflows {
1461            let steps = team.workflow_steps(*workflow);
1462            // Steps should be ordered 1..=N
1463            for (i, step) in steps.iter().enumerate() {
1464                assert_eq!(
1465                    step.order,
1466                    i + 1,
1467                    "Step {i} of {workflow} should have order {}",
1468                    i + 1
1469                );
1470            }
1471            // Steps should not be empty
1472            assert!(
1473                !steps.is_empty(),
1474                "Workflow {workflow} should have at least one step"
1475            );
1476        }
1477    }
1478}