Reorganize examples directory into logical topic-based subdirectories with comprehensive documentation: - templates/: ISO/ARC42 documentation templates - asset-management/: Asset management prototypes and demos - essays/: Long-form content examples - invoicing/: Invoice generation examples - plugins/: Plugin development examples - issue-demos/: Issue prevention demonstrations - design-patterns/: Design pattern examples Each subdirectory includes a README.txt file with topic description and contributor signatures based on file creation timestamps. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
261 lines
9.8 KiB
Python
261 lines
9.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Issue #59 Prevention Demonstration
|
|
|
|
This example shows how the Requirements Engineering Agent would have prevented
|
|
the interface compatibility issues and mock object mismatches encountered
|
|
during Issue #59 development.
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import Mock
|
|
from datetime import datetime, timezone
|
|
|
|
# Add project root to path for imports
|
|
project_root = Path(__file__).parent.parent
|
|
sys.path.insert(0, str(project_root))
|
|
|
|
from domain.issues.models import Issue, IssueState, Label
|
|
from tools.requirements_engineering_toolkit import RequirementsEngineeringAgent
|
|
|
|
|
|
def demonstrate_issue_59_problems():
|
|
"""Demonstrate the actual problems encountered in Issue #59."""
|
|
print("🚨 DEMONSTRATING ISSUE #59 PROBLEMS")
|
|
print("=" * 50)
|
|
|
|
print("\n❌ PROBLEM 1: Mock object didn't match domain model")
|
|
print("-" * 50)
|
|
|
|
# This is what was done in the original tests (WRONG)
|
|
mock_issue_wrong = Mock()
|
|
mock_issue_wrong.number = 59
|
|
mock_issue_wrong.title = "Test Issue"
|
|
mock_issue_wrong.state = "open" # ❌ String instead of enum!
|
|
mock_issue_wrong.labels = []
|
|
|
|
print(f"Mock state type: {type(mock_issue_wrong.state)} (should be IssueState enum)")
|
|
print(f"Mock state value: {mock_issue_wrong.state}")
|
|
|
|
# The real domain model uses enums
|
|
real_issue = Issue(
|
|
number=59,
|
|
title="Test Issue",
|
|
state=IssueState.OPEN, # ✅ Actual enum
|
|
labels=[],
|
|
created_at=datetime.now(timezone.utc),
|
|
updated_at=datetime.now(timezone.utc)
|
|
)
|
|
|
|
print(f"Real state type: {type(real_issue.state)}")
|
|
print(f"Real state value: {real_issue.state}")
|
|
|
|
print("\n❌ PROBLEM 2: Missing required attributes")
|
|
print("-" * 50)
|
|
|
|
# Original mock was missing critical attributes
|
|
print("Mock attributes:", [attr for attr in dir(mock_issue_wrong) if not attr.startswith('_')])
|
|
print("Real attributes:", [attr for attr in dir(real_issue) if not attr.startswith('_')])
|
|
|
|
missing_attrs = set(dir(real_issue)) - set(dir(mock_issue_wrong))
|
|
print(f"Missing attributes in mock: {[attr for attr in missing_attrs if not attr.startswith('_')]}")
|
|
|
|
|
|
def demonstrate_requirements_engineering_solution():
|
|
"""Demonstrate how the Requirements Engineering Agent would prevent these problems."""
|
|
print("\n\n✅ REQUIREMENTS ENGINEERING AGENT SOLUTION")
|
|
print("=" * 50)
|
|
|
|
agent = RequirementsEngineeringAgent(project_root)
|
|
|
|
print("\n🔍 STEP 1: Foundation Analysis")
|
|
print("-" * 30)
|
|
|
|
# Analyze existing domain models first
|
|
foundation_analysis = agent.analyze_project_foundations()
|
|
print(f"Found {foundation_analysis['foundation_analysis']['summary']['total_domain_models']} domain models")
|
|
|
|
# Show Issue model details
|
|
if 'Issue' in foundation_analysis['foundation_analysis']['domain_models']:
|
|
issue_model = foundation_analysis['foundation_analysis']['domain_models']['Issue']
|
|
print(f"Issue model attributes: {list(issue_model.attributes.keys())}")
|
|
print(f"Issue model methods: {issue_model.methods}")
|
|
|
|
print("\n📋 STEP 2: Generate Development Checklist")
|
|
print("-" * 30)
|
|
|
|
checklist = agent.generate_development_checklist("Issue Management CLI", {
|
|
"requires_issue_model": True,
|
|
"creates_new_interface": True
|
|
})
|
|
|
|
for phase in checklist:
|
|
print(f"\n{phase['phase']}:")
|
|
for task in phase['tasks']:
|
|
print(f" • {task}")
|
|
|
|
print("\n🧪 STEP 3: Correct Mock Creation")
|
|
print("-" * 30)
|
|
|
|
# This is how mocks should be created with the agent's guidance
|
|
mock_issue_correct = Mock(spec=Issue) # ✅ Use spec= parameter
|
|
mock_issue_correct.number = 59
|
|
mock_issue_correct.title = "Test Issue"
|
|
mock_issue_correct.state = IssueState.OPEN # ✅ Use actual enum
|
|
mock_issue_correct.labels = []
|
|
mock_issue_correct.created_at = datetime.now(timezone.utc) # ✅ Include all required attributes
|
|
mock_issue_correct.updated_at = datetime.now(timezone.utc)
|
|
|
|
print("✅ Correctly created mock with spec=Issue")
|
|
print(f"✅ State is proper enum: {type(mock_issue_correct.state)}")
|
|
print(f"✅ All required attributes included")
|
|
|
|
# Validate the mock
|
|
validation_result = agent.mock_validator.validate_mock_against_model(mock_issue_correct, "Issue")
|
|
if validation_result.is_valid:
|
|
print("✅ Mock validation passed!")
|
|
else:
|
|
print(f"❌ Mock validation failed: {validation_result.errors}")
|
|
|
|
|
|
def demonstrate_interface_compatibility_checking():
|
|
"""Demonstrate interface compatibility checking."""
|
|
print("\n\n🔌 INTERFACE COMPATIBILITY DEMONSTRATION")
|
|
print("=" * 50)
|
|
|
|
agent = RequirementsEngineeringAgent(project_root)
|
|
|
|
print("\n📊 Interface Analysis")
|
|
print("-" * 20)
|
|
|
|
# This would check if new plugin interface is compatible with existing repository
|
|
# In the actual Issue #59, this would have caught the mismatch between
|
|
# what the tests expected and what the actual GiteaIssueRepository provided
|
|
|
|
print("✅ Would verify that IssueBackend interface matches GiteaIssueRepository methods")
|
|
print("✅ Would catch async/sync mismatch (repository is async, plugin interface is sync)")
|
|
print("✅ Would identify missing adapter layer needed")
|
|
|
|
# Example compatibility check result
|
|
compatibility_result = {
|
|
"compatible": False,
|
|
"issues": [
|
|
"GiteaIssueRepository.get_issues() is async, but IssueBackend.list_issues() is sync",
|
|
"Parameter mismatch: repository uses issue_number (int), interface uses issue_id (str)",
|
|
"Repository returns additional attributes not defined in interface"
|
|
],
|
|
"recommendations": [
|
|
"Add async adapter layer",
|
|
"Standardize parameter types",
|
|
"Extend interface to include all repository attributes"
|
|
]
|
|
}
|
|
|
|
print("\nCompatibility check would have found:")
|
|
for issue in compatibility_result["issues"]:
|
|
print(f" ❌ {issue}")
|
|
|
|
print("\nRecommendations:")
|
|
for rec in compatibility_result["recommendations"]:
|
|
print(f" 💡 {rec}")
|
|
|
|
|
|
def demonstrate_correct_development_workflow():
|
|
"""Demonstrate the correct development workflow using the agent."""
|
|
print("\n\n🎯 CORRECT DEVELOPMENT WORKFLOW")
|
|
print("=" * 50)
|
|
|
|
print("\n📋 Phase 1: Foundation Analysis")
|
|
print("-" * 30)
|
|
print("✅ Analyze existing Issue domain model")
|
|
print("✅ Map GiteaIssueRepository interface")
|
|
print("✅ Understand async/sync requirements")
|
|
print("✅ Document existing infrastructure patterns")
|
|
|
|
print("\n📋 Phase 2: Interface Contract Definition")
|
|
print("-" * 30)
|
|
print("✅ Define IssueBackend abstract base class")
|
|
print("✅ Plan async adapter pattern")
|
|
print("✅ Ensure compatibility with existing infrastructure")
|
|
print("✅ Document interface contracts")
|
|
|
|
print("\n📋 Phase 3: Test Architecture Design")
|
|
print("-" * 30)
|
|
print("✅ Create mocks with Mock(spec=Issue)")
|
|
print("✅ Use actual enums and types")
|
|
print("✅ Include all required attributes")
|
|
print("✅ Plan integration test strategy")
|
|
|
|
print("\n📋 Phase 4: Implementation")
|
|
print("-" * 30)
|
|
print("✅ Implement IssueBackend base class")
|
|
print("✅ Create GiteaPlugin with async adapter")
|
|
print("✅ Add CLI commands using plugin manager")
|
|
print("✅ Maintain backward compatibility")
|
|
|
|
print("\n📋 Phase 5: Validation")
|
|
print("-" * 30)
|
|
print("✅ Validate all mocks match real objects")
|
|
print("✅ Test interface compatibility")
|
|
print("✅ Run integration tests")
|
|
print("✅ Verify end-to-end workflows")
|
|
|
|
|
|
def create_agent_usage_example():
|
|
"""Show actual agent usage commands."""
|
|
print("\n\n🛠️ AGENT USAGE COMMANDS")
|
|
print("=" * 50)
|
|
|
|
print("\n# Before starting Issue #59 development:")
|
|
print("python tools/requirements_engineering_toolkit.py analyze")
|
|
print("")
|
|
print("# Plan new interface evolution:")
|
|
print("python tools/requirements_engineering_toolkit.py plan-interface --interface IssueBackend")
|
|
print("")
|
|
print("# Generate development checklist:")
|
|
print("python tools/requirements_engineering_toolkit.py checklist --feature 'Issue Management CLI'")
|
|
print("")
|
|
print("# Validate test mocks:")
|
|
print("python tools/requirements_engineering_toolkit.py validate-mocks --test-file tests/test_issue_59_cli_interface.py")
|
|
|
|
print("\n📝 Integration with existing workflow:")
|
|
print("# Add to Makefile:")
|
|
print("validate-requirements:")
|
|
print("\tpython tools/requirements_engineering_toolkit.py analyze")
|
|
print("")
|
|
print("tdd-start: validate-requirements")
|
|
print("\t# Existing TDD start process")
|
|
|
|
|
|
def main():
|
|
"""Run the complete demonstration."""
|
|
print("ISSUE #59 PREVENTION DEMONSTRATION")
|
|
print("Requirements Engineering Agent")
|
|
print("=" * 60)
|
|
|
|
try:
|
|
demonstrate_issue_59_problems()
|
|
demonstrate_requirements_engineering_solution()
|
|
demonstrate_interface_compatibility_checking()
|
|
demonstrate_correct_development_workflow()
|
|
create_agent_usage_example()
|
|
|
|
print("\n\n🎉 SUMMARY")
|
|
print("=" * 20)
|
|
print("The Requirements Engineering Agent would have prevented Issue #59 problems by:")
|
|
print("1. ✅ Analyzing existing domain models before writing tests")
|
|
print("2. ✅ Ensuring mocks match actual object interfaces")
|
|
print("3. ✅ Catching enum vs string type mismatches")
|
|
print("4. ✅ Identifying missing async adapter layer")
|
|
print("5. ✅ Planning interface evolution with backward compatibility")
|
|
print("6. ✅ Providing clear development workflow guidance")
|
|
|
|
except Exception as e:
|
|
print(f"Error in demonstration: {e}")
|
|
print("Note: This demo requires the full project structure to run completely.")
|
|
print("The concepts and workflow are demonstrated above.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |