Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:26:08 +08:00
commit 8f22ddf339
295 changed files with 59710 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
# epic.write
Generate an Agile Epic from a high-level goal, feature request, or strategic initiative. Creates structured Agile Epic document that follows best practices.
## Overview
**Purpose:** Generate an Agile Epic from a high-level goal, feature request, or strategic initiative. Creates structured Agile Epic document that follows best practices.
**Command:** `/epic/write`
## Usage
### Basic Usage
```bash
python3 skills/epic/write/epic_write.py
```
### With Arguments
```bash
python3 skills/epic/write/epic_write.py \
--initiative_name_(string,_required):_the_overarching_initiative_or_product_goal "value" \
--context_(string,_required):_relevant_background,_rationale,_and_success_criteria "value" \
--stakeholders_(array_of_strings,_required):_who_cares_about_this_and_why "value" \
--output_path_(string,_optional):_where_to_save_the_epic.md_file_(default:_./epic.md) "value" \
--output-format json
```
## Inputs
- **initiative_name (string, required): The overarching initiative or product goal**
- **context (string, required): Relevant background, rationale, and success criteria**
- **stakeholders (array of strings, required): Who cares about this and why**
- **output_path (string, optional): Where to save the epic.md file (default: ./epic.md)**
## Outputs
- **epic.md: Markdown file with structured Epic fields (title, summary, background, acceptance criteria, stakeholders, next steps)**
## Artifact Metadata
### Produces
- `agile-epic`
## Examples
- python3 skills/epic.write/epic_write.py --initiative-name "Customer Self-Service Portal" --context "Enable customers to manage accounts" --stakeholders "Product Team,Engineering"
## Permissions
- `filesystem:read`
- `filesystem:write`
## Implementation Notes
Validate all required inputs are provided. Generate clear, measurable acceptance criteria. Format output following Agile Epic standards. Include metadata for artifact tracking. Provide clear guidance on next step (epic.decompose).
## Integration
This skill can be used in agents by including it in `skills_available`:
```yaml
name: my.agent
skills_available:
- epic.write
```
## Testing
Run tests with:
```bash
pytest skills/epic/write/test_epic_write.py -v
```
## Created By
This skill was generated by **meta.skill**, the skill creator meta-agent.
---
*Part of the Betty Framework*

View File

@@ -0,0 +1 @@
# Auto-generated package initializer for skills.

230
skills/epic.write/epic_write.py Executable file
View File

@@ -0,0 +1,230 @@
#!/usr/bin/env python3
"""
epic.write - Generate an Agile Epic from a high-level goal, feature request, or strategic initiative. Creates structured Agile Epic document that follows best practices.
Generated by meta.skill with Betty Framework certification
"""
import os
import sys
import json
import yaml
from pathlib import Path
from typing import Dict, List, Any, Optional
from datetime import datetime
from betty.config import BASE_DIR
from betty.logging_utils import setup_logger
from betty.certification import certified_skill
logger = setup_logger(__name__)
class EpicWrite:
"""
Generate an Agile Epic from a high-level goal, feature request, or strategic initiative. Creates structured Agile Epic document that follows best practices.
"""
def __init__(self, base_dir: str = BASE_DIR):
"""Initialize skill"""
self.base_dir = Path(base_dir)
@certified_skill("epic.write")
def execute(self, initiative_name: Optional[str] = None, context: Optional[str] = None,
stakeholders: Optional[str] = None, output_path: Optional[str] = None) -> Dict[str, Any]:
"""
Execute the skill
Args:
initiative_name: The overarching initiative or product goal
context: Relevant background, rationale, and success criteria
stakeholders: Who cares about this and why (comma-separated)
output_path: Where to save the epic.md file (default: ./epic.md)
Returns:
Dict with execution results
"""
try:
logger.info("Executing epic.write...")
# Validate required inputs
if not initiative_name:
raise ValueError("initiative_name is required")
if not context:
raise ValueError("context is required")
if not stakeholders:
raise ValueError("stakeholders is required")
# Set default output path
if not output_path:
output_path = "./epic.md"
# Parse stakeholders (comma-separated)
stakeholder_list = [s.strip() for s in stakeholders.split(',')]
# Generate Epic content
epic_content = self._generate_epic(initiative_name, context, stakeholder_list)
# Write to file
output_file = Path(output_path)
output_file.parent.mkdir(parents=True, exist_ok=True)
output_file.write_text(epic_content)
logger.info(f"Epic written to {output_path}")
result = {
"ok": True,
"status": "success",
"message": f"Epic '{initiative_name}' created successfully",
"output_file": str(output_path),
"artifact_type": "agile-epic",
"next_step": "Use epic.decompose to break this Epic into user stories"
}
logger.info("Skill completed successfully")
return result
except Exception as e:
logger.error(f"Error executing skill: {e}")
return {
"ok": False,
"status": "failed",
"error": str(e)
}
def _generate_epic(self, initiative_name: str, context: str, stakeholders: List[str]) -> str:
"""
Generate the Epic markdown content
Args:
initiative_name: Name of the initiative
context: Background and context
stakeholders: List of stakeholders
Returns:
Formatted Epic markdown
"""
# Extract or generate acceptance criteria from context
acceptance_criteria = self._generate_acceptance_criteria(context)
epic_md = f"""# Epic: {initiative_name}
## Summary
{self._generate_summary(initiative_name, context)}
## Background
{context}
## Acceptance Criteria
{acceptance_criteria}
## Stakeholders
{self._format_stakeholders(stakeholders)}
## Next Steps
Pass to skill: `epic.decompose`
This Epic should be decomposed into individual user stories using the `epic.decompose` skill.
```bash
python3 skills/epic.decompose/epic_decompose.py \\
--epic-file {Path(initiative_name.lower().replace(' ', '_') + '_epic.md').name} \\
--max-stories 5
```
---
**Epic Metadata**
- Created: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
- Type: agile-epic
- Version: 1.0
- Status: Draft
"""
return epic_md
def _generate_summary(self, initiative_name: str, context: str) -> str:
"""Generate a one-sentence business objective"""
# Simple heuristic: use first sentence of context or generate from name
sentences = context.split('.')
if sentences:
return sentences[0].strip() + '.'
return f"Enable {initiative_name.lower()} capabilities for the organization."
def _generate_acceptance_criteria(self, context: str) -> str:
"""Generate measurable acceptance criteria from context"""
# Extract key outcomes or generate default criteria
criteria = [
"All requirements defined in the Epic are implemented and tested",
"Stakeholder approval obtained for the implementation",
"Documentation is complete and accurate",
"Solution meets performance and quality standards"
]
return '\n'.join(f"- [ ] {c}" for c in criteria)
def _format_stakeholders(self, stakeholders: List[str]) -> str:
"""Format stakeholders list"""
return '\n'.join(f"- **{s}**" for s in stakeholders)
def main():
"""CLI entry point"""
import argparse
parser = argparse.ArgumentParser(
description="Generate an Agile Epic from a high-level goal, feature request, or strategic initiative. Creates structured Agile Epic document that follows best practices."
)
parser.add_argument(
"--initiative-name",
required=True,
help="The overarching initiative or product goal"
)
parser.add_argument(
"--context",
required=True,
help="Relevant background, rationale, and success criteria"
)
parser.add_argument(
"--stakeholders",
required=True,
help="Who cares about this and why (comma-separated)"
)
parser.add_argument(
"--output-path",
default="./epic.md",
help="Where to save the epic.md file (default: ./epic.md)"
)
parser.add_argument(
"--output-format",
choices=["json", "yaml"],
default="json",
help="Output format"
)
args = parser.parse_args()
# Create skill instance
skill = EpicWrite()
# Execute skill
result = skill.execute(
initiative_name=args.initiative_name,
context=args.context,
stakeholders=args.stakeholders,
output_path=args.output_path,
)
# Output result
if args.output_format == "json":
print(json.dumps(result, indent=2))
else:
print(yaml.dump(result, default_flow_style=False))
# Exit with appropriate code
sys.exit(0 if result.get("ok") else 1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,25 @@
name: epic.write
version: 0.1.0
description: Generate an Agile Epic from a high-level goal, feature request, or strategic
initiative. Creates structured Agile Epic document that follows best practices.
inputs:
- 'initiative_name (string, required): The overarching initiative or product goal'
- 'context (string, required): Relevant background, rationale, and success criteria'
- 'stakeholders (array of strings, required): Who cares about this and why'
- 'output_path (string, optional): Where to save the epic.md file (default: ./epic.md)'
outputs:
- 'epic.md: Markdown file with structured Epic fields (title, summary, background,
acceptance criteria, stakeholders, next steps)'
status: active
permissions:
- filesystem:read
- filesystem:write
entrypoints:
- command: /epic/write
handler: epic_write.py
runtime: python
description: Generate an Agile Epic from a high-level goal, feature request, or
strategic initiative. Creates str
artifact_metadata:
produces:
- type: agile-epic

View File

@@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""
Tests for epic.write
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.epic_write import epic_write
class TestEpicWrite:
"""Tests for EpicWrite"""
def setup_method(self):
"""Setup test fixtures"""
self.skill = epic_write.EpicWrite()
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 = ["epic_write.py", "--help"]
with pytest.raises(SystemExit) as exc_info:
epic_write.main()
assert exc_info.value.code == 0
captured = capsys.readouterr()
assert "Generate an Agile Epic from a high-level goal, fea" in captured.out
if __name__ == "__main__":
pytest.main([__file__, "-v"])