Initial commit
This commit is contained in:
106
skills/workflow.orchestrate/README.md
Normal file
106
skills/workflow.orchestrate/README.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# workflow.orchestrate
|
||||
|
||||
Orchestrate multi-artifact workflows by coordinating specialized agents and artifact creation skills. Creates complete artifact sets for complex initiatives by managing dependencies, sequencing work, and ensuring artifact consistency. Supports common SDLC workflows like project initiation, security reviews, data design, test planning, deployment planning, and full SDLC cycles.
|
||||
|
||||
## Overview
|
||||
|
||||
**Purpose:** Orchestrate multi-artifact workflows by coordinating specialized agents and artifact creation skills. Creates complete artifact sets for complex initiatives by managing dependencies, sequencing work, and ensuring artifact consistency. Supports common SDLC workflows like project initiation, security reviews, data design, test planning, deployment planning, and full SDLC cycles.
|
||||
|
||||
**Command:** `/workflow/orchestrate`
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```bash
|
||||
python3 skills/workflow/orchestrate/workflow_orchestrate.py
|
||||
```
|
||||
|
||||
### With Arguments
|
||||
|
||||
```bash
|
||||
python3 skills/workflow/orchestrate/workflow_orchestrate.py \
|
||||
--workflow_type_(string,_required):_type_of_workflow_to_execute_(project-initiation,_security-review,_data-design,_test-planning,_deployment-planning,_full-sdlc) "value" \
|
||||
--description_(string,_required):_initiative_or_project_description_for_context "value" \
|
||||
--output_directory_(string,_required):_directory_where_all_workflow_artifacts_will_be_created "value" \
|
||||
--author_(string,_optional):_author_name_for_generated_artifacts_(default:_"workflow_orchestrator") "value" \
|
||||
--classification_(string,_optional):_classification_level_(public,_internal,_confidential,_restricted,_default:_internal) "value" \
|
||||
--output-format json
|
||||
```
|
||||
|
||||
## Inputs
|
||||
|
||||
- **workflow_type (string, required): Type of workflow to execute (project-initiation, security-review, data-design, test-planning, deployment-planning, full-sdlc)**
|
||||
- **description (string, required): Initiative or project description for context**
|
||||
- **output_directory (string, required): Directory where all workflow artifacts will be created**
|
||||
- **author (string, optional): Author name for generated artifacts (default: "Workflow Orchestrator")**
|
||||
- **classification (string, optional): Classification level (Public, Internal, Confidential, Restricted, default: Internal)**
|
||||
|
||||
## Outputs
|
||||
|
||||
- **workflow-execution-report: Complete workflow execution report with all generated artifacts**
|
||||
- **artifact-manifest: Manifest of all created artifacts with paths and validation status**
|
||||
- **All artifacts specified by the workflow type (e.g., business-case, project-charter, etc.)**
|
||||
- **None (initiates workflows from user context)**
|
||||
- **workflow-execution-report**
|
||||
- **artifact-manifest**
|
||||
- **Plus all artifacts specified by the chosen workflow type**
|
||||
- **filesystem:read**
|
||||
- **filesystem:write**
|
||||
- **artifact.create skill (to create individual artifacts)**
|
||||
- **artifact.validate skill (to validate created artifacts)**
|
||||
- **Template files in templates/ directory**
|
||||
- **Call artifact.create with appropriate type and context**
|
||||
- **Call artifact.validate to check quality**
|
||||
- **Track created artifacts and validation results**
|
||||
- **Handle missing dependencies gracefully**
|
||||
- **Continue workflow even if individual artifacts fail**
|
||||
- **Report all failures in execution report**
|
||||
- **Return overall success based on whether any artifacts were created**
|
||||
|
||||
## Examples
|
||||
|
||||
- -author "Product Team"
|
||||
- business-case.yaml
|
||||
- project-charter.yaml
|
||||
- raid-log.yaml
|
||||
- stakeholder-analysis.yaml
|
||||
- project-initiation-workflow-report.yaml
|
||||
- -classification Confidential
|
||||
- threat-model.yaml
|
||||
- security-architecture-diagram.yaml
|
||||
- security-assessment.yaml
|
||||
- vulnerability-management-plan.yaml
|
||||
- security-review-workflow-report.yaml
|
||||
- -author "Enterprise Architecture"
|
||||
- workflow_type: One of the supported workflow types
|
||||
- description: Project/initiative description
|
||||
- output_directory: Where to save all artifacts
|
||||
- --author: Author name for artifacts
|
||||
- --classification: Classification level (Public|Internal|Confidential|Restricted)
|
||||
|
||||
## Integration
|
||||
|
||||
This skill can be used in agents by including it in `skills_available`:
|
||||
|
||||
```yaml
|
||||
name: my.agent
|
||||
skills_available:
|
||||
- workflow.orchestrate
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Run tests with:
|
||||
|
||||
```bash
|
||||
pytest skills/workflow/orchestrate/test_workflow_orchestrate.py -v
|
||||
```
|
||||
|
||||
## Created By
|
||||
|
||||
This skill was generated by **meta.skill**, the skill creator meta-agent.
|
||||
|
||||
---
|
||||
|
||||
*Part of the Betty Framework*
|
||||
1
skills/workflow.orchestrate/__init__.py
Normal file
1
skills/workflow.orchestrate/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Auto-generated package initializer for skills.
|
||||
48
skills/workflow.orchestrate/skill.yaml
Normal file
48
skills/workflow.orchestrate/skill.yaml
Normal file
@@ -0,0 +1,48 @@
|
||||
name: workflow.orchestrate
|
||||
version: 0.1.0
|
||||
description: Orchestrate multi-artifact workflows by coordinating specialized agents
|
||||
and artifact creation skills. Creates complete artifact sets for complex initiatives
|
||||
by managing dependencies, sequencing work, and ensuring artifact consistency. Supports
|
||||
common SDLC workflows like project initiation, security reviews, data design, test
|
||||
planning, deployment planning, and full SDLC cycles.
|
||||
inputs:
|
||||
- 'workflow_type (string, required): Type of workflow to execute (project-initiation,
|
||||
security-review, data-design, test-planning, deployment-planning, full-sdlc)'
|
||||
- 'description (string, required): Initiative or project description for context'
|
||||
- 'output_directory (string, required): Directory where all workflow artifacts will
|
||||
be created'
|
||||
- 'author (string, optional): Author name for generated artifacts (default: "Workflow
|
||||
Orchestrator")'
|
||||
- 'classification (string, optional): Classification level (Public, Internal, Confidential,
|
||||
Restricted, default: Internal)'
|
||||
outputs:
|
||||
- 'workflow-execution-report: Complete workflow execution report with all generated
|
||||
artifacts'
|
||||
- 'artifact-manifest: Manifest of all created artifacts with paths and validation
|
||||
status'
|
||||
- All artifacts specified by the workflow type (e.g., business-case, project-charter,
|
||||
etc.)
|
||||
- None (initiates workflows from user context)
|
||||
- workflow-execution-report
|
||||
- artifact-manifest
|
||||
- Plus all artifacts specified by the chosen workflow type
|
||||
- filesystem:read
|
||||
- filesystem:write
|
||||
- artifact.create skill (to create individual artifacts)
|
||||
- artifact.validate skill (to validate created artifacts)
|
||||
- Template files in templates/ directory
|
||||
- Call artifact.create with appropriate type and context
|
||||
- Call artifact.validate to check quality
|
||||
- Track created artifacts and validation results
|
||||
- Handle missing dependencies gracefully
|
||||
- Continue workflow even if individual artifacts fail
|
||||
- Report all failures in execution report
|
||||
- Return overall success based on whether any artifacts were created
|
||||
status: active
|
||||
permissions: []
|
||||
entrypoints:
|
||||
- command: /workflow/orchestrate
|
||||
handler: workflow_orchestrate.py
|
||||
runtime: python
|
||||
description: Orchestrate multi-artifact workflows by coordinating specialized agents
|
||||
and artifact creation skills
|
||||
62
skills/workflow.orchestrate/test_workflow_orchestrate.py
Normal file
62
skills/workflow.orchestrate/test_workflow_orchestrate.py
Normal file
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Tests for workflow.orchestrate
|
||||
|
||||
Generated by meta.skill
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
|
||||
|
||||
from skills.workflow_orchestrate import workflow_orchestrate
|
||||
|
||||
|
||||
class TestWorkflowOrchestrate:
|
||||
"""Tests for WorkflowOrchestrate"""
|
||||
|
||||
def setup_method(self):
|
||||
"""Setup test fixtures"""
|
||||
self.skill = workflow_orchestrate.WorkflowOrchestrate()
|
||||
|
||||
def test_initialization(self):
|
||||
"""Test skill initializes correctly"""
|
||||
assert self.skill is not None
|
||||
assert self.skill.base_dir is not None
|
||||
|
||||
def test_execute_basic(self):
|
||||
"""Test basic execution"""
|
||||
result = self.skill.execute()
|
||||
|
||||
assert result is not None
|
||||
assert "ok" in result
|
||||
assert "status" in result
|
||||
|
||||
def test_execute_success(self):
|
||||
"""Test successful execution"""
|
||||
result = self.skill.execute()
|
||||
|
||||
assert result["ok"] is True
|
||||
assert result["status"] == "success"
|
||||
|
||||
# TODO: Add more specific tests based on skill functionality
|
||||
|
||||
|
||||
def test_cli_help(capsys):
|
||||
"""Test CLI help message"""
|
||||
sys.argv = ["workflow_orchestrate.py", "--help"]
|
||||
|
||||
with pytest.raises(SystemExit) as exc_info:
|
||||
workflow_orchestrate.main()
|
||||
|
||||
assert exc_info.value.code == 0
|
||||
captured = capsys.readouterr()
|
||||
assert "Orchestrate multi-artifact workflows by coordinati" in captured.out
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
217
skills/workflow.orchestrate/workflow_orchestrate.py
Executable file
217
skills/workflow.orchestrate/workflow_orchestrate.py
Executable file
@@ -0,0 +1,217 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
workflow.orchestrate skill - Multi-artifact workflow orchestration
|
||||
|
||||
Coordinates specialized agents to create complete artifact sets for complex initiatives.
|
||||
Manages dependencies, sequencing, and validation.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any, List, Optional
|
||||
|
||||
from betty.skill_executor import execute_skill_in_process
|
||||
|
||||
|
||||
# Workflow definitions
|
||||
WORKFLOWS = {
|
||||
"project-initiation": {
|
||||
"description": "Complete project initiation artifact set",
|
||||
"artifacts": [
|
||||
{"type": "business-case", "agent": "strategy.architect", "priority": 1},
|
||||
{"type": "project-charter", "agent": "governance.manager", "priority": 2, "depends_on": ["business-case"]},
|
||||
{"type": "raid-log", "agent": "governance.manager", "priority": 3},
|
||||
{"type": "stakeholder-analysis", "agent": "governance.manager", "priority": 3},
|
||||
]
|
||||
},
|
||||
"security-review": {
|
||||
"description": "Comprehensive security assessment",
|
||||
"artifacts": [
|
||||
{"type": "threat-model", "agent": "security.architect", "priority": 1},
|
||||
{"type": "security-architecture-diagram", "agent": "security.architect", "priority": 2, "depends_on": ["threat-model"]},
|
||||
{"type": "security-assessment", "agent": "security.architect", "priority": 2},
|
||||
{"type": "vulnerability-management-plan", "agent": "security.architect", "priority": 3},
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def create_artifact(artifact_type: str, context: str, output_path: str, metadata: Optional[Dict] = None) -> Dict[str, Any]:
|
||||
"""Create a single artifact using artifact.create skill"""
|
||||
try:
|
||||
args = [artifact_type, context, output_path]
|
||||
|
||||
if metadata and metadata.get('author'):
|
||||
args.extend(["--author", metadata['author']])
|
||||
|
||||
result = execute_skill_in_process("artifact.create", args, timeout=30)
|
||||
|
||||
if result["returncode"] == 0:
|
||||
return {
|
||||
"success": True,
|
||||
"artifact_path": output_path,
|
||||
"artifact_type": artifact_type
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"success": False,
|
||||
"error": result["stderr"] or result["stdout"],
|
||||
"artifact_type": artifact_type
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"artifact_type": artifact_type
|
||||
}
|
||||
|
||||
|
||||
def orchestrate_workflow(
|
||||
workflow_type: str,
|
||||
context: str,
|
||||
output_directory: str,
|
||||
author: str = "Workflow Orchestrator"
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Orchestrate multi-artifact workflow
|
||||
"""
|
||||
|
||||
if workflow_type not in WORKFLOWS:
|
||||
return {
|
||||
"success": False,
|
||||
"error": f"Unknown workflow type: {workflow_type}",
|
||||
"available_workflows": list(WORKFLOWS.keys())
|
||||
}
|
||||
|
||||
workflow = WORKFLOWS[workflow_type]
|
||||
|
||||
# Create output directory
|
||||
output_path = Path(output_directory)
|
||||
output_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Initialize workflow report
|
||||
workflow_report = {
|
||||
"workflow_type": workflow_type,
|
||||
"description": workflow.get("description"),
|
||||
"started_at": datetime.now().isoformat(),
|
||||
"artifacts_created": [],
|
||||
"artifacts_failed": [],
|
||||
}
|
||||
|
||||
metadata = {"author": author}
|
||||
|
||||
# Sort artifacts by priority
|
||||
artifacts_to_create = sorted(workflow["artifacts"], key=lambda x: x.get("priority", 99))
|
||||
|
||||
# Track created artifacts
|
||||
created_artifacts = {}
|
||||
|
||||
print(f"\n{'='*70}")
|
||||
print(f"🚀 Starting {workflow_type} workflow")
|
||||
print(f"{'='*70}\n")
|
||||
|
||||
# Create each artifact
|
||||
for i, artifact_spec in enumerate(artifacts_to_create, 1):
|
||||
artifact_type = artifact_spec["type"]
|
||||
depends_on = artifact_spec.get("depends_on", [])
|
||||
|
||||
print(f"[{i}/{len(artifacts_to_create)}] Creating {artifact_type}...")
|
||||
|
||||
# Check dependencies
|
||||
missing_deps = [dep for dep in depends_on if dep not in created_artifacts]
|
||||
if missing_deps:
|
||||
print(f" ⚠️ Skipping - missing dependencies: {missing_deps}\n")
|
||||
workflow_report["artifacts_failed"].append({
|
||||
"artifact_type": artifact_type,
|
||||
"reason": f"Missing dependencies: {missing_deps}"
|
||||
})
|
||||
continue
|
||||
|
||||
# Build context with dependencies
|
||||
artifact_context = context
|
||||
if depends_on:
|
||||
dep_info = ", ".join([f"{dep} at {created_artifacts[dep]}" for dep in depends_on])
|
||||
artifact_context += f"\n\nRelated artifacts: {dep_info}"
|
||||
|
||||
output_file = output_path / f"{artifact_type}.yaml"
|
||||
|
||||
# Create artifact
|
||||
result = create_artifact(
|
||||
artifact_type=artifact_type,
|
||||
context=artifact_context,
|
||||
output_path=str(output_file),
|
||||
metadata=metadata
|
||||
)
|
||||
|
||||
if result["success"]:
|
||||
print(f" ✅ Created: {output_file}\n")
|
||||
created_artifacts[artifact_type] = str(output_file)
|
||||
|
||||
workflow_report["artifacts_created"].append({
|
||||
"artifact_type": artifact_type,
|
||||
"artifact_path": str(output_file),
|
||||
"created_at": datetime.now().isoformat()
|
||||
})
|
||||
else:
|
||||
print(f" ❌ Failed: {result.get('error', 'Unknown error')}\n")
|
||||
workflow_report["artifacts_failed"].append({
|
||||
"artifact_type": artifact_type,
|
||||
"reason": result.get("error", "Unknown error")
|
||||
})
|
||||
|
||||
# Calculate summary
|
||||
total_artifacts = len(artifacts_to_create)
|
||||
created_count = len(workflow_report["artifacts_created"])
|
||||
|
||||
workflow_report["completed_at"] = datetime.now().isoformat()
|
||||
workflow_report["summary"] = {
|
||||
"total_artifacts": total_artifacts,
|
||||
"created": created_count,
|
||||
"failed": len(workflow_report["artifacts_failed"]),
|
||||
"success_rate": f"{(created_count / total_artifacts * 100):.0f}%" if total_artifacts > 0 else "0%"
|
||||
}
|
||||
|
||||
# Save workflow report
|
||||
report_file = output_path / f"{workflow_type}-workflow-report.yaml"
|
||||
with open(report_file, 'w') as f:
|
||||
yaml.dump(workflow_report, f, default_flow_style=False, sort_keys=False)
|
||||
|
||||
print(f"{'='*70}")
|
||||
print(f"Created: {created_count}/{total_artifacts} artifacts")
|
||||
print(f"📄 Report: {report_file}")
|
||||
print(f"{'='*70}\n")
|
||||
|
||||
return {
|
||||
"success": created_count > 0,
|
||||
"workflow_report": workflow_report,
|
||||
"report_file": str(report_file)
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
"""CLI entry point"""
|
||||
parser = argparse.ArgumentParser(description='Orchestrate multi-artifact workflows')
|
||||
parser.add_argument('workflow_type', choices=list(WORKFLOWS.keys()), help='Workflow type')
|
||||
parser.add_argument('description', help='Initiative description')
|
||||
parser.add_argument('output_directory', help='Output directory')
|
||||
parser.add_argument('--author', default='Workflow Orchestrator', help='Author name')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
result = orchestrate_workflow(
|
||||
workflow_type=args.workflow_type,
|
||||
context=args.description,
|
||||
output_directory=args.output_directory,
|
||||
author=args.author
|
||||
)
|
||||
|
||||
return 0 if result["success"] else 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user