1use serde::{Deserialize, Serialize};
13use std::fmt;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
17#[serde(rename_all = "snake_case")]
18pub enum DevRole {
19 Architect,
21 Implementer,
23 Tester,
25 Reviewer,
27 Debugger,
29 DevOps,
31 SecurityAuditor,
33 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#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
54#[serde(rename_all = "snake_case")]
55pub enum DevWorkflow {
56 ImplementFeature,
58 FixBug,
60 Refactor,
62 AddTests,
64 SecurityAudit,
66 CodeReview,
68 Optimize,
70 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
89const 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#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct WorkflowStep {
104 pub order: usize,
106 pub role: DevRole,
108 pub action: String,
110 pub instructions: String,
112 pub expected_output: String,
114 pub gate: Option<QualityGate>,
116 pub retryable: bool,
118 pub max_retries: usize,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct QualityGate {
125 pub description: String,
127 pub check_type: GateCheck,
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
133#[serde(rename_all = "snake_case")]
134pub enum GateCheck {
135 TestsPass,
137 ReviewScore {
139 min_score: u32,
141 },
142 NoSecurityFindings {
144 max_severity: String,
146 },
147 CompileSuccess,
149 Custom {
151 check: String,
153 },
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
158pub struct DevTeamConfig {
159 pub name: String,
161 pub roles: Vec<DevRole>,
163 pub role_models: Vec<(DevRole, String)>,
165 pub max_parallel: usize,
167 pub enforce_gates: bool,
169 pub max_iterations: usize,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct WorkflowResult {
176 pub workflow: DevWorkflow,
178 pub status: WorkflowStatus,
180 pub steps_completed: usize,
182 pub steps_total: usize,
184 pub artifacts: Vec<WorkflowArtifact>,
186 pub quality_scores: Vec<(String, f32)>,
188 pub notes: Vec<String>,
190}
191
192#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
194#[serde(rename_all = "snake_case")]
195pub enum WorkflowStatus {
196 Completed,
198 Failed {
200 step: usize,
202 reason: String,
204 },
205 GateBlocked {
207 step: usize,
209 gate: String,
211 },
212 Cancelled,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct WorkflowArtifact {
219 pub name: String,
221 pub artifact_type: ArtifactType,
223 pub content: String,
225}
226
227#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
229#[serde(rename_all = "snake_case")]
230pub enum ArtifactType {
231 Plan,
233 Code,
235 TestResults,
237 ReviewReport,
239 SecurityReport,
241 Documentation,
243 Diff,
245}
246
247#[derive(Debug, Clone)]
253pub struct DevTeam {
254 config: DevTeamConfig,
255}
256
257impl DevTeam {
258 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 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 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 pub fn with_config(config: DevTeamConfig) -> Self {
324 Self { config }
325 }
326
327 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 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 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 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 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 *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 !artifacts.is_empty()
420 }
421 }
422 }
423
424 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 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 pub fn available_workflows(&self) -> Vec<DevWorkflow> {
507 ALL_WORKFLOWS.to_vec()
508 }
509
510 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 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
563fn 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
577fn 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
591fn 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
605fn 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
702fn 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
775fn 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
849fn 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
900fn 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
974fn 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
1026fn 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
1095fn 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#[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 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 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 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 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 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 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 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 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 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 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 assert!(
1473 !steps.is_empty(),
1474 "Workflow {workflow} should have at least one step"
1475 );
1476 }
1477 }
1478}