empathy-framework 3.7.0__py3-none-any.whl → 3.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coach_wizards/code_reviewer_README.md +60 -0
- coach_wizards/code_reviewer_wizard.py +180 -0
- {empathy_framework-3.7.0.dist-info → empathy_framework-3.8.0.dist-info}/METADATA +148 -11
- empathy_framework-3.8.0.dist-info/RECORD +333 -0
- {empathy_framework-3.7.0.dist-info → empathy_framework-3.8.0.dist-info}/top_level.txt +5 -1
- empathy_healthcare_plugin/monitors/__init__.py +9 -0
- empathy_healthcare_plugin/monitors/clinical_protocol_monitor.py +315 -0
- empathy_healthcare_plugin/monitors/monitoring/__init__.py +44 -0
- empathy_healthcare_plugin/monitors/monitoring/protocol_checker.py +300 -0
- empathy_healthcare_plugin/monitors/monitoring/protocol_loader.py +214 -0
- empathy_healthcare_plugin/monitors/monitoring/sensor_parsers.py +306 -0
- empathy_healthcare_plugin/monitors/monitoring/trajectory_analyzer.py +389 -0
- empathy_llm_toolkit/agent_factory/__init__.py +53 -0
- empathy_llm_toolkit/agent_factory/adapters/__init__.py +85 -0
- empathy_llm_toolkit/agent_factory/adapters/autogen_adapter.py +312 -0
- empathy_llm_toolkit/agent_factory/adapters/crewai_adapter.py +454 -0
- empathy_llm_toolkit/agent_factory/adapters/haystack_adapter.py +298 -0
- empathy_llm_toolkit/agent_factory/adapters/langchain_adapter.py +362 -0
- empathy_llm_toolkit/agent_factory/adapters/langgraph_adapter.py +333 -0
- empathy_llm_toolkit/agent_factory/adapters/native.py +228 -0
- empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +426 -0
- empathy_llm_toolkit/agent_factory/base.py +305 -0
- empathy_llm_toolkit/agent_factory/crews/__init__.py +67 -0
- empathy_llm_toolkit/agent_factory/crews/code_review.py +1113 -0
- empathy_llm_toolkit/agent_factory/crews/health_check.py +1246 -0
- empathy_llm_toolkit/agent_factory/crews/refactoring.py +1128 -0
- empathy_llm_toolkit/agent_factory/crews/security_audit.py +1018 -0
- empathy_llm_toolkit/agent_factory/decorators.py +286 -0
- empathy_llm_toolkit/agent_factory/factory.py +558 -0
- empathy_llm_toolkit/agent_factory/framework.py +192 -0
- empathy_llm_toolkit/agent_factory/memory_integration.py +324 -0
- empathy_llm_toolkit/agent_factory/resilient.py +320 -0
- empathy_llm_toolkit/cli/__init__.py +8 -0
- empathy_llm_toolkit/cli/sync_claude.py +487 -0
- empathy_llm_toolkit/code_health.py +150 -3
- empathy_llm_toolkit/config/__init__.py +29 -0
- empathy_llm_toolkit/config/unified.py +295 -0
- empathy_llm_toolkit/routing/__init__.py +32 -0
- empathy_llm_toolkit/routing/model_router.py +362 -0
- empathy_llm_toolkit/security/IMPLEMENTATION_SUMMARY.md +413 -0
- empathy_llm_toolkit/security/PHASE2_COMPLETE.md +384 -0
- empathy_llm_toolkit/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- empathy_llm_toolkit/security/QUICK_REFERENCE.md +316 -0
- empathy_llm_toolkit/security/README.md +262 -0
- empathy_llm_toolkit/security/__init__.py +62 -0
- empathy_llm_toolkit/security/audit_logger.py +929 -0
- empathy_llm_toolkit/security/audit_logger_example.py +152 -0
- empathy_llm_toolkit/security/pii_scrubber.py +640 -0
- empathy_llm_toolkit/security/secrets_detector.py +678 -0
- empathy_llm_toolkit/security/secrets_detector_example.py +304 -0
- empathy_llm_toolkit/security/secure_memdocs.py +1192 -0
- empathy_llm_toolkit/security/secure_memdocs_example.py +278 -0
- empathy_llm_toolkit/wizards/__init__.py +38 -0
- empathy_llm_toolkit/wizards/base_wizard.py +364 -0
- empathy_llm_toolkit/wizards/customer_support_wizard.py +190 -0
- empathy_llm_toolkit/wizards/healthcare_wizard.py +362 -0
- empathy_llm_toolkit/wizards/patient_assessment_README.md +64 -0
- empathy_llm_toolkit/wizards/patient_assessment_wizard.py +193 -0
- empathy_llm_toolkit/wizards/technology_wizard.py +194 -0
- empathy_os/__init__.py +52 -52
- empathy_os/adaptive/__init__.py +13 -0
- empathy_os/adaptive/task_complexity.py +127 -0
- empathy_os/cache/__init__.py +117 -0
- empathy_os/cache/base.py +166 -0
- empathy_os/cache/dependency_manager.py +253 -0
- empathy_os/cache/hash_only.py +248 -0
- empathy_os/cache/hybrid.py +390 -0
- empathy_os/cache/storage.py +282 -0
- empathy_os/cli.py +118 -8
- empathy_os/cli_unified.py +121 -1
- empathy_os/config/__init__.py +63 -0
- empathy_os/config/xml_config.py +239 -0
- empathy_os/config.py +2 -1
- empathy_os/dashboard/__init__.py +15 -0
- empathy_os/dashboard/server.py +743 -0
- empathy_os/memory/__init__.py +195 -0
- empathy_os/memory/claude_memory.py +466 -0
- empathy_os/memory/config.py +224 -0
- empathy_os/memory/control_panel.py +1298 -0
- empathy_os/memory/edges.py +179 -0
- empathy_os/memory/graph.py +567 -0
- empathy_os/memory/long_term.py +1194 -0
- empathy_os/memory/nodes.py +179 -0
- empathy_os/memory/redis_bootstrap.py +540 -0
- empathy_os/memory/security/__init__.py +31 -0
- empathy_os/memory/security/audit_logger.py +930 -0
- empathy_os/memory/security/pii_scrubber.py +640 -0
- empathy_os/memory/security/secrets_detector.py +678 -0
- empathy_os/memory/short_term.py +2119 -0
- empathy_os/memory/storage/__init__.py +15 -0
- empathy_os/memory/summary_index.py +583 -0
- empathy_os/memory/unified.py +619 -0
- empathy_os/metrics/__init__.py +12 -0
- empathy_os/metrics/prompt_metrics.py +190 -0
- empathy_os/models/__init__.py +136 -0
- empathy_os/models/__main__.py +13 -0
- empathy_os/models/cli.py +655 -0
- empathy_os/models/empathy_executor.py +354 -0
- empathy_os/models/executor.py +252 -0
- empathy_os/models/fallback.py +671 -0
- empathy_os/models/provider_config.py +563 -0
- empathy_os/models/registry.py +382 -0
- empathy_os/models/tasks.py +302 -0
- empathy_os/models/telemetry.py +548 -0
- empathy_os/models/token_estimator.py +378 -0
- empathy_os/models/validation.py +274 -0
- empathy_os/monitoring/__init__.py +52 -0
- empathy_os/monitoring/alerts.py +23 -0
- empathy_os/monitoring/alerts_cli.py +268 -0
- empathy_os/monitoring/multi_backend.py +271 -0
- empathy_os/monitoring/otel_backend.py +363 -0
- empathy_os/optimization/__init__.py +19 -0
- empathy_os/optimization/context_optimizer.py +272 -0
- empathy_os/plugins/__init__.py +28 -0
- empathy_os/plugins/base.py +361 -0
- empathy_os/plugins/registry.py +268 -0
- empathy_os/project_index/__init__.py +30 -0
- empathy_os/project_index/cli.py +335 -0
- empathy_os/project_index/crew_integration.py +430 -0
- empathy_os/project_index/index.py +425 -0
- empathy_os/project_index/models.py +501 -0
- empathy_os/project_index/reports.py +473 -0
- empathy_os/project_index/scanner.py +538 -0
- empathy_os/prompts/__init__.py +61 -0
- empathy_os/prompts/config.py +77 -0
- empathy_os/prompts/context.py +177 -0
- empathy_os/prompts/parser.py +285 -0
- empathy_os/prompts/registry.py +313 -0
- empathy_os/prompts/templates.py +208 -0
- empathy_os/resilience/__init__.py +56 -0
- empathy_os/resilience/circuit_breaker.py +256 -0
- empathy_os/resilience/fallback.py +179 -0
- empathy_os/resilience/health.py +300 -0
- empathy_os/resilience/retry.py +209 -0
- empathy_os/resilience/timeout.py +135 -0
- empathy_os/routing/__init__.py +43 -0
- empathy_os/routing/chain_executor.py +433 -0
- empathy_os/routing/classifier.py +217 -0
- empathy_os/routing/smart_router.py +234 -0
- empathy_os/routing/wizard_registry.py +307 -0
- empathy_os/trust/__init__.py +28 -0
- empathy_os/trust/circuit_breaker.py +579 -0
- empathy_os/validation/__init__.py +19 -0
- empathy_os/validation/xml_validator.py +281 -0
- empathy_os/wizard_factory_cli.py +170 -0
- empathy_os/workflows/__init__.py +360 -0
- empathy_os/workflows/base.py +1660 -0
- empathy_os/workflows/bug_predict.py +962 -0
- empathy_os/workflows/code_review.py +960 -0
- empathy_os/workflows/code_review_adapters.py +310 -0
- empathy_os/workflows/code_review_pipeline.py +720 -0
- empathy_os/workflows/config.py +600 -0
- empathy_os/workflows/dependency_check.py +648 -0
- empathy_os/workflows/document_gen.py +1069 -0
- empathy_os/workflows/documentation_orchestrator.py +1205 -0
- empathy_os/workflows/health_check.py +679 -0
- empathy_os/workflows/keyboard_shortcuts/__init__.py +39 -0
- empathy_os/workflows/keyboard_shortcuts/generators.py +386 -0
- empathy_os/workflows/keyboard_shortcuts/parsers.py +414 -0
- empathy_os/workflows/keyboard_shortcuts/prompts.py +295 -0
- empathy_os/workflows/keyboard_shortcuts/schema.py +193 -0
- empathy_os/workflows/keyboard_shortcuts/workflow.py +505 -0
- empathy_os/workflows/manage_documentation.py +804 -0
- empathy_os/workflows/new_sample_workflow1.py +146 -0
- empathy_os/workflows/new_sample_workflow1_README.md +150 -0
- empathy_os/workflows/perf_audit.py +687 -0
- empathy_os/workflows/pr_review.py +748 -0
- empathy_os/workflows/progress.py +445 -0
- empathy_os/workflows/progress_server.py +322 -0
- empathy_os/workflows/refactor_plan.py +693 -0
- empathy_os/workflows/release_prep.py +808 -0
- empathy_os/workflows/research_synthesis.py +404 -0
- empathy_os/workflows/secure_release.py +585 -0
- empathy_os/workflows/security_adapters.py +297 -0
- empathy_os/workflows/security_audit.py +1046 -0
- empathy_os/workflows/step_config.py +234 -0
- empathy_os/workflows/test5.py +125 -0
- empathy_os/workflows/test5_README.md +158 -0
- empathy_os/workflows/test_gen.py +1855 -0
- empathy_os/workflows/test_lifecycle.py +526 -0
- empathy_os/workflows/test_maintenance.py +626 -0
- empathy_os/workflows/test_maintenance_cli.py +590 -0
- empathy_os/workflows/test_maintenance_crew.py +821 -0
- empathy_os/workflows/xml_enhanced_crew.py +285 -0
- empathy_software_plugin/cli/__init__.py +120 -0
- empathy_software_plugin/cli/inspect.py +362 -0
- empathy_software_plugin/cli.py +3 -1
- empathy_software_plugin/wizards/__init__.py +42 -0
- empathy_software_plugin/wizards/advanced_debugging_wizard.py +392 -0
- empathy_software_plugin/wizards/agent_orchestration_wizard.py +511 -0
- empathy_software_plugin/wizards/ai_collaboration_wizard.py +503 -0
- empathy_software_plugin/wizards/ai_context_wizard.py +441 -0
- empathy_software_plugin/wizards/ai_documentation_wizard.py +503 -0
- empathy_software_plugin/wizards/base_wizard.py +288 -0
- empathy_software_plugin/wizards/book_chapter_wizard.py +519 -0
- empathy_software_plugin/wizards/code_review_wizard.py +606 -0
- empathy_software_plugin/wizards/debugging/__init__.py +50 -0
- empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +414 -0
- empathy_software_plugin/wizards/debugging/config_loaders.py +442 -0
- empathy_software_plugin/wizards/debugging/fix_applier.py +469 -0
- empathy_software_plugin/wizards/debugging/language_patterns.py +383 -0
- empathy_software_plugin/wizards/debugging/linter_parsers.py +470 -0
- empathy_software_plugin/wizards/debugging/verification.py +369 -0
- empathy_software_plugin/wizards/enhanced_testing_wizard.py +537 -0
- empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +816 -0
- empathy_software_plugin/wizards/multi_model_wizard.py +501 -0
- empathy_software_plugin/wizards/pattern_extraction_wizard.py +422 -0
- empathy_software_plugin/wizards/pattern_retriever_wizard.py +400 -0
- empathy_software_plugin/wizards/performance/__init__.py +9 -0
- empathy_software_plugin/wizards/performance/bottleneck_detector.py +221 -0
- empathy_software_plugin/wizards/performance/profiler_parsers.py +278 -0
- empathy_software_plugin/wizards/performance/trajectory_analyzer.py +429 -0
- empathy_software_plugin/wizards/performance_profiling_wizard.py +305 -0
- empathy_software_plugin/wizards/prompt_engineering_wizard.py +425 -0
- empathy_software_plugin/wizards/rag_pattern_wizard.py +461 -0
- empathy_software_plugin/wizards/security/__init__.py +32 -0
- empathy_software_plugin/wizards/security/exploit_analyzer.py +290 -0
- empathy_software_plugin/wizards/security/owasp_patterns.py +241 -0
- empathy_software_plugin/wizards/security/vulnerability_scanner.py +604 -0
- empathy_software_plugin/wizards/security_analysis_wizard.py +322 -0
- empathy_software_plugin/wizards/security_learning_wizard.py +740 -0
- empathy_software_plugin/wizards/tech_debt_wizard.py +726 -0
- empathy_software_plugin/wizards/testing/__init__.py +27 -0
- empathy_software_plugin/wizards/testing/coverage_analyzer.py +459 -0
- empathy_software_plugin/wizards/testing/quality_analyzer.py +531 -0
- empathy_software_plugin/wizards/testing/test_suggester.py +533 -0
- empathy_software_plugin/wizards/testing_wizard.py +274 -0
- hot_reload/README.md +473 -0
- hot_reload/__init__.py +62 -0
- hot_reload/config.py +84 -0
- hot_reload/integration.py +228 -0
- hot_reload/reloader.py +298 -0
- hot_reload/watcher.py +179 -0
- hot_reload/websocket.py +176 -0
- scaffolding/README.md +589 -0
- scaffolding/__init__.py +35 -0
- scaffolding/__main__.py +14 -0
- scaffolding/cli.py +240 -0
- test_generator/__init__.py +38 -0
- test_generator/__main__.py +14 -0
- test_generator/cli.py +226 -0
- test_generator/generator.py +325 -0
- test_generator/risk_analyzer.py +216 -0
- workflow_patterns/__init__.py +33 -0
- workflow_patterns/behavior.py +249 -0
- workflow_patterns/core.py +76 -0
- workflow_patterns/output.py +99 -0
- workflow_patterns/registry.py +255 -0
- workflow_patterns/structural.py +288 -0
- workflow_scaffolding/__init__.py +11 -0
- workflow_scaffolding/__main__.py +12 -0
- workflow_scaffolding/cli.py +206 -0
- workflow_scaffolding/generator.py +265 -0
- agents/code_inspection/patterns/inspection/recurring_B112.json +0 -18
- agents/code_inspection/patterns/inspection/recurring_F541.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_FORMAT.json +0 -25
- agents/code_inspection/patterns/inspection/recurring_bug_20250822_def456.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20250915_abc123.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_3c5b9951.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_97c0f72f.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_a0871d53.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_a9b6ec41.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_null_001.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_builtin.json +0 -16
- agents/compliance_anticipation_agent.py +0 -1422
- agents/compliance_db.py +0 -339
- agents/epic_integration_wizard.py +0 -530
- agents/notifications.py +0 -291
- agents/trust_building_behaviors.py +0 -872
- empathy_framework-3.7.0.dist-info/RECORD +0 -105
- {empathy_framework-3.7.0.dist-info → empathy_framework-3.8.0.dist-info}/WHEEL +0 -0
- {empathy_framework-3.7.0.dist-info → empathy_framework-3.8.0.dist-info}/entry_points.txt +0 -0
- {empathy_framework-3.7.0.dist-info → empathy_framework-3.8.0.dist-info}/licenses/LICENSE +0 -0
- /empathy_os/{monitoring.py → agent_monitoring.py} +0 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"""Test generator core implementation.
|
|
2
|
+
|
|
3
|
+
Generates comprehensive tests for wizards using Jinja2 templates
|
|
4
|
+
and risk-based prioritization.
|
|
5
|
+
|
|
6
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
7
|
+
Licensed under Fair Source 0.9
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from jinja2 import Environment, FileSystemLoader
|
|
16
|
+
|
|
17
|
+
from patterns import get_pattern_registry
|
|
18
|
+
from patterns.structural import LinearFlowPattern, PhasedProcessingPattern
|
|
19
|
+
|
|
20
|
+
from .risk_analyzer import RiskAnalyzer
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TestGenerator:
|
|
26
|
+
"""Generates tests for wizards based on patterns and risk analysis.
|
|
27
|
+
|
|
28
|
+
Uses Jinja2 templates to generate:
|
|
29
|
+
- Unit tests with risk-prioritized coverage
|
|
30
|
+
- Integration tests for multi-step workflows
|
|
31
|
+
- E2E tests for critical paths
|
|
32
|
+
- Test fixtures for common patterns
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, template_dir: Path | None = None):
|
|
36
|
+
"""Initialize test generator.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
template_dir: Directory containing Jinja2 templates
|
|
40
|
+
(defaults to test_generator/templates/)
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
if template_dir is None:
|
|
44
|
+
template_dir = Path(__file__).parent / "templates"
|
|
45
|
+
|
|
46
|
+
self.template_dir = template_dir
|
|
47
|
+
self.env = Environment(
|
|
48
|
+
loader=FileSystemLoader(str(template_dir)),
|
|
49
|
+
trim_blocks=True,
|
|
50
|
+
lstrip_blocks=True,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
self.risk_analyzer = RiskAnalyzer()
|
|
54
|
+
self.registry = get_pattern_registry()
|
|
55
|
+
|
|
56
|
+
def generate_tests(
|
|
57
|
+
self,
|
|
58
|
+
wizard_id: str,
|
|
59
|
+
pattern_ids: list[str],
|
|
60
|
+
wizard_module: str | None = None,
|
|
61
|
+
wizard_class: str | None = None,
|
|
62
|
+
) -> dict[str, str]:
|
|
63
|
+
"""Generate tests for a wizard.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
wizard_id: Wizard identifier
|
|
67
|
+
pattern_ids: List of pattern IDs used by wizard
|
|
68
|
+
wizard_module: Python module path (e.g., "wizards.soap_note")
|
|
69
|
+
wizard_class: Wizard class name (e.g., "SOAPNoteWizard")
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Dictionary with test types:
|
|
73
|
+
{
|
|
74
|
+
"unit": "...", # Unit test code
|
|
75
|
+
"integration": "...", # Integration test code (if applicable)
|
|
76
|
+
"fixtures": "...", # Test fixtures
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
"""
|
|
80
|
+
logger.info(f"Generating tests for wizard: {wizard_id}")
|
|
81
|
+
|
|
82
|
+
# Perform risk analysis
|
|
83
|
+
risk_analysis = self.risk_analyzer.analyze(wizard_id, pattern_ids)
|
|
84
|
+
|
|
85
|
+
# Infer module and class if not provided
|
|
86
|
+
if not wizard_module:
|
|
87
|
+
wizard_module = self._infer_module(wizard_id)
|
|
88
|
+
|
|
89
|
+
if not wizard_class:
|
|
90
|
+
wizard_class = self._infer_class_name(wizard_id)
|
|
91
|
+
|
|
92
|
+
# Gather template context
|
|
93
|
+
context = self._build_template_context(
|
|
94
|
+
wizard_id=wizard_id,
|
|
95
|
+
pattern_ids=pattern_ids,
|
|
96
|
+
wizard_module=wizard_module,
|
|
97
|
+
wizard_class=wizard_class,
|
|
98
|
+
risk_analysis=risk_analysis,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Generate unit tests (always)
|
|
102
|
+
unit_tests = self._generate_unit_tests(context)
|
|
103
|
+
|
|
104
|
+
# Generate integration tests (for multi-step wizards)
|
|
105
|
+
integration_tests = None
|
|
106
|
+
if self._needs_integration_tests(pattern_ids):
|
|
107
|
+
integration_tests = self._generate_integration_tests(context)
|
|
108
|
+
|
|
109
|
+
# Generate test fixtures
|
|
110
|
+
fixtures = self._generate_fixtures(context)
|
|
111
|
+
|
|
112
|
+
logger.info(
|
|
113
|
+
f"Generated tests for {wizard_id}: "
|
|
114
|
+
f"unit={len(unit_tests)} chars, "
|
|
115
|
+
f"integration={'yes' if integration_tests else 'no'}, "
|
|
116
|
+
f"fixtures={len(fixtures)} chars"
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
"unit": unit_tests,
|
|
121
|
+
"integration": integration_tests,
|
|
122
|
+
"fixtures": fixtures,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
def _build_template_context(
|
|
126
|
+
self,
|
|
127
|
+
wizard_id: str,
|
|
128
|
+
pattern_ids: list[str],
|
|
129
|
+
wizard_module: str,
|
|
130
|
+
wizard_class: str,
|
|
131
|
+
risk_analysis: Any,
|
|
132
|
+
) -> dict:
|
|
133
|
+
"""Build Jinja2 template context.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
wizard_id: Wizard identifier
|
|
137
|
+
pattern_ids: Pattern IDs
|
|
138
|
+
wizard_module: Module path
|
|
139
|
+
wizard_class: Class name
|
|
140
|
+
risk_analysis: RiskAnalysis object
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Context dictionary for templates
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
# Get pattern details
|
|
147
|
+
patterns = [self.registry.get(pid) for pid in pattern_ids if self.registry.get(pid)]
|
|
148
|
+
|
|
149
|
+
# Check for specific patterns
|
|
150
|
+
has_linear_flow = "linear_flow" in pattern_ids
|
|
151
|
+
has_phased = "phased_processing" in pattern_ids
|
|
152
|
+
has_approval = "approval" in pattern_ids
|
|
153
|
+
has_async = True # Assume async by default for modern wizards
|
|
154
|
+
|
|
155
|
+
# Get linear flow details if present
|
|
156
|
+
total_steps = None
|
|
157
|
+
if has_linear_flow:
|
|
158
|
+
linear_pattern = self.registry.get("linear_flow")
|
|
159
|
+
if isinstance(linear_pattern, LinearFlowPattern):
|
|
160
|
+
total_steps = linear_pattern.total_steps
|
|
161
|
+
|
|
162
|
+
# Get phases if present
|
|
163
|
+
phases = []
|
|
164
|
+
if has_phased:
|
|
165
|
+
phased_pattern = self.registry.get("phased_processing")
|
|
166
|
+
if isinstance(phased_pattern, PhasedProcessingPattern):
|
|
167
|
+
phases = phased_pattern.phases
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
"wizard_id": wizard_id,
|
|
171
|
+
"wizard_module": wizard_module,
|
|
172
|
+
"wizard_class": wizard_class,
|
|
173
|
+
"pattern_ids": pattern_ids,
|
|
174
|
+
"patterns": patterns,
|
|
175
|
+
"risk_analysis": risk_analysis,
|
|
176
|
+
"has_async": has_async,
|
|
177
|
+
"has_linear_flow": has_linear_flow,
|
|
178
|
+
"has_phased": has_phased,
|
|
179
|
+
"has_approval": has_approval,
|
|
180
|
+
"total_steps": total_steps,
|
|
181
|
+
"phases": phases,
|
|
182
|
+
"timestamp": datetime.now().isoformat(),
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
def _generate_unit_tests(self, context: dict) -> str:
|
|
186
|
+
"""Generate unit tests from template.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
context: Template context
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
Generated unit test code
|
|
193
|
+
|
|
194
|
+
"""
|
|
195
|
+
template = self.env.get_template("unit_test.py.jinja2")
|
|
196
|
+
return template.render(**context)
|
|
197
|
+
|
|
198
|
+
def _generate_integration_tests(self, context: dict) -> str:
|
|
199
|
+
"""Generate integration tests.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
context: Template context
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
Generated integration test code
|
|
206
|
+
|
|
207
|
+
"""
|
|
208
|
+
# For now, return a simple integration test template
|
|
209
|
+
# In full implementation, would use integration_test.py.jinja2
|
|
210
|
+
return f'''"""Integration tests for {context["wizard_id"]} wizard.
|
|
211
|
+
|
|
212
|
+
Auto-generated by Empathy Framework Test Generator
|
|
213
|
+
Tests end-to-end wizard workflows.
|
|
214
|
+
"""
|
|
215
|
+
|
|
216
|
+
import pytest
|
|
217
|
+
from {context["wizard_module"]} import {context["wizard_class"]}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class TestIntegration{context["wizard_class"]}:
|
|
221
|
+
"""Integration tests for {context["wizard_id"]} wizard."""
|
|
222
|
+
|
|
223
|
+
@pytest.fixture
|
|
224
|
+
async def wizard(self):
|
|
225
|
+
"""Create wizard instance."""
|
|
226
|
+
return {context["wizard_class"]}()
|
|
227
|
+
|
|
228
|
+
@pytest.mark.asyncio
|
|
229
|
+
async def test_complete_wizard_workflow(self, wizard):
|
|
230
|
+
"""Test complete wizard workflow end-to-end."""
|
|
231
|
+
# Start wizard
|
|
232
|
+
session = await wizard.start()
|
|
233
|
+
wizard_id = session["wizard_id"]
|
|
234
|
+
|
|
235
|
+
# Complete all steps with valid data
|
|
236
|
+
# TODO: Add step completion logic
|
|
237
|
+
|
|
238
|
+
# Verify final state
|
|
239
|
+
assert session.get("completed", False) is True
|
|
240
|
+
'''
|
|
241
|
+
|
|
242
|
+
def _generate_fixtures(self, context: dict) -> str:
|
|
243
|
+
"""Generate test fixtures.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
context: Template context
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
Generated fixture code
|
|
250
|
+
|
|
251
|
+
"""
|
|
252
|
+
return f'''"""Test fixtures for {context["wizard_id"]} wizard.
|
|
253
|
+
|
|
254
|
+
Auto-generated by Empathy Framework Test Generator
|
|
255
|
+
Provides common test data and mocks.
|
|
256
|
+
"""
|
|
257
|
+
|
|
258
|
+
import pytest
|
|
259
|
+
from unittest.mock import MagicMock
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
@pytest.fixture
|
|
263
|
+
def sample_{context["wizard_id"]}_data():
|
|
264
|
+
"""Sample data for {context["wizard_id"]} wizard."""
|
|
265
|
+
return {{
|
|
266
|
+
"field1": "test value 1",
|
|
267
|
+
"field2": "test value 2",
|
|
268
|
+
}}
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@pytest.fixture
|
|
272
|
+
def mock_{context["wizard_id"]}_dependencies():
|
|
273
|
+
"""Mock dependencies for {context["wizard_id"]} wizard."""
|
|
274
|
+
return {{
|
|
275
|
+
"database": MagicMock(),
|
|
276
|
+
"api_client": MagicMock(),
|
|
277
|
+
}}
|
|
278
|
+
'''
|
|
279
|
+
|
|
280
|
+
def _needs_integration_tests(self, pattern_ids: list[str]) -> bool:
|
|
281
|
+
"""Determine if integration tests are needed.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
pattern_ids: Pattern IDs
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
True if integration tests recommended
|
|
288
|
+
|
|
289
|
+
"""
|
|
290
|
+
# Integration tests for multi-step or phased wizards
|
|
291
|
+
return "linear_flow" in pattern_ids or "phased_processing" in pattern_ids
|
|
292
|
+
|
|
293
|
+
def _infer_module(self, wizard_id: str) -> str:
|
|
294
|
+
"""Infer module path from wizard ID.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
wizard_id: Wizard identifier
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
Inferred module path
|
|
301
|
+
|
|
302
|
+
"""
|
|
303
|
+
# Try to determine wizard location
|
|
304
|
+
# This is a simple heuristic - can be improved
|
|
305
|
+
if wizard_id in ["soap_note", "sbar", "care_plan"]:
|
|
306
|
+
return f"wizards.{wizard_id}"
|
|
307
|
+
elif wizard_id in ["debugging", "testing", "security"]:
|
|
308
|
+
return f"coach_wizards.{wizard_id}_wizard"
|
|
309
|
+
else:
|
|
310
|
+
return f"wizards.{wizard_id}_wizard"
|
|
311
|
+
|
|
312
|
+
def _infer_class_name(self, wizard_id: str) -> str:
|
|
313
|
+
"""Infer wizard class name from ID.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
wizard_id: Wizard identifier
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
Inferred class name
|
|
320
|
+
|
|
321
|
+
"""
|
|
322
|
+
# Convert snake_case to PascalCase and add "Wizard"
|
|
323
|
+
parts = wizard_id.split("_")
|
|
324
|
+
class_name = "".join(part.capitalize() for part in parts)
|
|
325
|
+
return f"{class_name}Wizard"
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""Risk analyzer for test generation.
|
|
2
|
+
|
|
3
|
+
Analyzes wizard patterns to identify critical paths and determine
|
|
4
|
+
appropriate test coverage levels.
|
|
5
|
+
|
|
6
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
7
|
+
Licensed under Fair Source 0.9
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
|
|
13
|
+
from patterns import get_pattern_registry
|
|
14
|
+
from patterns.behavior import PredictionPattern, RiskAssessmentPattern
|
|
15
|
+
from patterns.structural import PhasedProcessingPattern
|
|
16
|
+
from patterns.validation import ApprovalPattern, StepValidationPattern
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class RiskAnalysis:
|
|
23
|
+
"""Risk analysis results for a wizard."""
|
|
24
|
+
|
|
25
|
+
wizard_id: str
|
|
26
|
+
pattern_ids: list[str]
|
|
27
|
+
critical_paths: list[str] = field(default_factory=list)
|
|
28
|
+
high_risk_inputs: list[str] = field(default_factory=list)
|
|
29
|
+
validation_points: list[str] = field(default_factory=list)
|
|
30
|
+
recommended_coverage: int = 80 # Percentage
|
|
31
|
+
test_priorities: dict[str, int] = field(default_factory=dict) # test_name -> priority (1-5)
|
|
32
|
+
|
|
33
|
+
def get_critical_test_cases(self) -> list[str]:
|
|
34
|
+
"""Get list of critical test case names.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
List of critical test cases to implement
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
test_cases = []
|
|
41
|
+
|
|
42
|
+
# Critical paths become test cases
|
|
43
|
+
for path in self.critical_paths:
|
|
44
|
+
test_case = f"test_{path.lower().replace(' ', '_').replace('-', '_')}"
|
|
45
|
+
test_cases.append(test_case)
|
|
46
|
+
|
|
47
|
+
# High-risk inputs become test cases
|
|
48
|
+
for input_risk in self.high_risk_inputs:
|
|
49
|
+
test_case = f"test_{input_risk.lower().replace(' ', '_')}_validation"
|
|
50
|
+
test_cases.append(test_case)
|
|
51
|
+
|
|
52
|
+
return test_cases
|
|
53
|
+
|
|
54
|
+
def to_dict(self) -> dict:
|
|
55
|
+
"""Convert to dictionary."""
|
|
56
|
+
return {
|
|
57
|
+
"wizard_id": self.wizard_id,
|
|
58
|
+
"pattern_ids": self.pattern_ids,
|
|
59
|
+
"critical_paths": self.critical_paths,
|
|
60
|
+
"high_risk_inputs": self.high_risk_inputs,
|
|
61
|
+
"validation_points": self.validation_points,
|
|
62
|
+
"recommended_coverage": self.recommended_coverage,
|
|
63
|
+
"test_priorities": self.test_priorities,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class RiskAnalyzer:
|
|
68
|
+
"""Analyzes wizard patterns to determine testing requirements.
|
|
69
|
+
|
|
70
|
+
Uses pattern analysis to identify:
|
|
71
|
+
- Critical execution paths
|
|
72
|
+
- High-risk input scenarios
|
|
73
|
+
- Required validation points
|
|
74
|
+
- Recommended test coverage level
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def __init__(self):
|
|
78
|
+
"""Initialize risk analyzer."""
|
|
79
|
+
self.registry = get_pattern_registry()
|
|
80
|
+
|
|
81
|
+
def analyze(self, wizard_id: str, pattern_ids: list[str]) -> RiskAnalysis:
|
|
82
|
+
"""Analyze wizard patterns for risk.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
wizard_id: Wizard identifier
|
|
86
|
+
pattern_ids: List of pattern IDs used by wizard
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
RiskAnalysis with recommendations
|
|
90
|
+
|
|
91
|
+
"""
|
|
92
|
+
logger.info(f"Analyzing risk for wizard: {wizard_id}")
|
|
93
|
+
|
|
94
|
+
analysis = RiskAnalysis(
|
|
95
|
+
wizard_id=wizard_id,
|
|
96
|
+
pattern_ids=pattern_ids,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Analyze each pattern
|
|
100
|
+
for pattern_id in pattern_ids:
|
|
101
|
+
pattern = self.registry.get(pattern_id)
|
|
102
|
+
if not pattern:
|
|
103
|
+
logger.warning(f"Pattern not found: {pattern_id}")
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
self._analyze_pattern(pattern, analysis)
|
|
107
|
+
|
|
108
|
+
# Calculate recommended coverage based on risk
|
|
109
|
+
self._calculate_coverage(analysis)
|
|
110
|
+
|
|
111
|
+
# Prioritize tests
|
|
112
|
+
self._prioritize_tests(analysis)
|
|
113
|
+
|
|
114
|
+
logger.info(
|
|
115
|
+
f"Risk analysis complete: {len(analysis.critical_paths)} critical paths, "
|
|
116
|
+
f"{analysis.recommended_coverage}% coverage recommended"
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
return analysis
|
|
120
|
+
|
|
121
|
+
def _analyze_pattern(self, pattern, analysis: RiskAnalysis) -> None:
|
|
122
|
+
"""Analyze a specific pattern for risks.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
pattern: Pattern to analyze
|
|
126
|
+
analysis: RiskAnalysis to update
|
|
127
|
+
|
|
128
|
+
"""
|
|
129
|
+
# Approval patterns are CRITICAL - must test preview → approval flow
|
|
130
|
+
if isinstance(pattern, ApprovalPattern):
|
|
131
|
+
analysis.critical_paths.append("approval_workflow")
|
|
132
|
+
analysis.high_risk_inputs.append("save_without_preview")
|
|
133
|
+
analysis.high_risk_inputs.append("save_without_approval")
|
|
134
|
+
analysis.validation_points.append("preview_generated")
|
|
135
|
+
analysis.validation_points.append("user_approved")
|
|
136
|
+
|
|
137
|
+
# Step validation patterns - test step sequencing
|
|
138
|
+
elif isinstance(pattern, StepValidationPattern):
|
|
139
|
+
analysis.critical_paths.append("step_sequence_validation")
|
|
140
|
+
analysis.high_risk_inputs.append("skip_step")
|
|
141
|
+
analysis.high_risk_inputs.append("wrong_step_number")
|
|
142
|
+
analysis.validation_points.append("current_step")
|
|
143
|
+
|
|
144
|
+
# Phased processing - each phase is a critical path
|
|
145
|
+
elif isinstance(pattern, PhasedProcessingPattern):
|
|
146
|
+
for phase in pattern.phases:
|
|
147
|
+
analysis.critical_paths.append(f"phase_{phase.name}")
|
|
148
|
+
if phase.required:
|
|
149
|
+
analysis.validation_points.append(f"{phase.name}_completed")
|
|
150
|
+
|
|
151
|
+
# Risk assessment patterns - test risk detection
|
|
152
|
+
elif isinstance(pattern, RiskAssessmentPattern):
|
|
153
|
+
analysis.critical_paths.append("risk_assessment")
|
|
154
|
+
analysis.validation_points.append("alert_level")
|
|
155
|
+
for level in pattern.risk_levels:
|
|
156
|
+
analysis.high_risk_inputs.append(f"{level.name}_threshold")
|
|
157
|
+
|
|
158
|
+
# Prediction patterns - test predictions
|
|
159
|
+
elif isinstance(pattern, PredictionPattern):
|
|
160
|
+
analysis.critical_paths.append("prediction_generation")
|
|
161
|
+
for pred_type in pattern.prediction_types:
|
|
162
|
+
analysis.validation_points.append(pred_type)
|
|
163
|
+
|
|
164
|
+
def _calculate_coverage(self, analysis: RiskAnalysis) -> None:
|
|
165
|
+
"""Calculate recommended test coverage.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
analysis: RiskAnalysis to update
|
|
169
|
+
|
|
170
|
+
"""
|
|
171
|
+
# Base coverage
|
|
172
|
+
base_coverage = 70
|
|
173
|
+
|
|
174
|
+
# Add 5% for each critical path
|
|
175
|
+
critical_bonus = min(20, len(analysis.critical_paths) * 5)
|
|
176
|
+
|
|
177
|
+
# Add 3% for each validation point
|
|
178
|
+
validation_bonus = min(10, len(analysis.validation_points) * 3)
|
|
179
|
+
|
|
180
|
+
# Cap at 95%
|
|
181
|
+
analysis.recommended_coverage = min(
|
|
182
|
+
95,
|
|
183
|
+
base_coverage + critical_bonus + validation_bonus,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
def _prioritize_tests(self, analysis: RiskAnalysis) -> None:
|
|
187
|
+
"""Assign priorities to test cases.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
analysis: RiskAnalysis to update
|
|
191
|
+
|
|
192
|
+
"""
|
|
193
|
+
# Priority levels: 1 (critical) to 5 (nice-to-have)
|
|
194
|
+
|
|
195
|
+
# Critical paths = Priority 1
|
|
196
|
+
for path in analysis.critical_paths:
|
|
197
|
+
test_name = f"test_{path}"
|
|
198
|
+
analysis.test_priorities[test_name] = 1
|
|
199
|
+
|
|
200
|
+
# High-risk inputs = Priority 2
|
|
201
|
+
for input_risk in analysis.high_risk_inputs:
|
|
202
|
+
test_name = f"test_{input_risk}_validation"
|
|
203
|
+
analysis.test_priorities[test_name] = 2
|
|
204
|
+
|
|
205
|
+
# Validation points = Priority 3
|
|
206
|
+
for validation in analysis.validation_points:
|
|
207
|
+
test_name = f"test_{validation}"
|
|
208
|
+
if test_name not in analysis.test_priorities:
|
|
209
|
+
analysis.test_priorities[test_name] = 3
|
|
210
|
+
|
|
211
|
+
# Success path = Priority 4
|
|
212
|
+
analysis.test_priorities["test_success_path"] = 4
|
|
213
|
+
analysis.test_priorities["test_happy_path"] = 4
|
|
214
|
+
|
|
215
|
+
# Edge cases = Priority 5
|
|
216
|
+
analysis.test_priorities["test_edge_cases"] = 5
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Workflow Pattern Library.
|
|
2
|
+
|
|
3
|
+
Extracted patterns from 17 existing workflows for rapid workflow generation.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .behavior import CodeScannerPattern, ConditionalTierPattern, ConfigDrivenPattern
|
|
10
|
+
from .core import PatternCategory, WorkflowComplexity, WorkflowPattern
|
|
11
|
+
from .output import ResultDataclassPattern
|
|
12
|
+
from .registry import WorkflowPatternRegistry, get_workflow_pattern_registry
|
|
13
|
+
from .structural import CrewBasedPattern, MultiStagePattern, SingleStagePattern
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
# Core
|
|
17
|
+
"WorkflowPattern",
|
|
18
|
+
"PatternCategory",
|
|
19
|
+
"WorkflowComplexity",
|
|
20
|
+
# Structural
|
|
21
|
+
"SingleStagePattern",
|
|
22
|
+
"MultiStagePattern",
|
|
23
|
+
"CrewBasedPattern",
|
|
24
|
+
# Behavioral
|
|
25
|
+
"ConditionalTierPattern",
|
|
26
|
+
"ConfigDrivenPattern",
|
|
27
|
+
"CodeScannerPattern",
|
|
28
|
+
# Output
|
|
29
|
+
"ResultDataclassPattern",
|
|
30
|
+
# Registry
|
|
31
|
+
"WorkflowPatternRegistry",
|
|
32
|
+
"get_workflow_pattern_registry",
|
|
33
|
+
]
|