empathy-framework 4.6.6__py3-none-any.whl → 4.7.1__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.
Files changed (273) hide show
  1. empathy_framework-4.7.1.dist-info/METADATA +690 -0
  2. empathy_framework-4.7.1.dist-info/RECORD +379 -0
  3. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/top_level.txt +1 -2
  4. empathy_healthcare_plugin/monitors/monitoring/__init__.py +9 -9
  5. empathy_llm_toolkit/agent_factory/__init__.py +6 -6
  6. empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +7 -10
  7. empathy_llm_toolkit/agents_md/__init__.py +22 -0
  8. empathy_llm_toolkit/agents_md/loader.py +218 -0
  9. empathy_llm_toolkit/agents_md/parser.py +271 -0
  10. empathy_llm_toolkit/agents_md/registry.py +307 -0
  11. empathy_llm_toolkit/commands/__init__.py +51 -0
  12. empathy_llm_toolkit/commands/context.py +375 -0
  13. empathy_llm_toolkit/commands/loader.py +301 -0
  14. empathy_llm_toolkit/commands/models.py +231 -0
  15. empathy_llm_toolkit/commands/parser.py +371 -0
  16. empathy_llm_toolkit/commands/registry.py +429 -0
  17. empathy_llm_toolkit/config/__init__.py +8 -8
  18. empathy_llm_toolkit/config/unified.py +3 -7
  19. empathy_llm_toolkit/context/__init__.py +22 -0
  20. empathy_llm_toolkit/context/compaction.py +455 -0
  21. empathy_llm_toolkit/context/manager.py +434 -0
  22. empathy_llm_toolkit/hooks/__init__.py +24 -0
  23. empathy_llm_toolkit/hooks/config.py +306 -0
  24. empathy_llm_toolkit/hooks/executor.py +289 -0
  25. empathy_llm_toolkit/hooks/registry.py +302 -0
  26. empathy_llm_toolkit/hooks/scripts/__init__.py +39 -0
  27. empathy_llm_toolkit/hooks/scripts/evaluate_session.py +201 -0
  28. empathy_llm_toolkit/hooks/scripts/first_time_init.py +285 -0
  29. empathy_llm_toolkit/hooks/scripts/pre_compact.py +207 -0
  30. empathy_llm_toolkit/hooks/scripts/session_end.py +183 -0
  31. empathy_llm_toolkit/hooks/scripts/session_start.py +163 -0
  32. empathy_llm_toolkit/hooks/scripts/suggest_compact.py +225 -0
  33. empathy_llm_toolkit/learning/__init__.py +30 -0
  34. empathy_llm_toolkit/learning/evaluator.py +438 -0
  35. empathy_llm_toolkit/learning/extractor.py +514 -0
  36. empathy_llm_toolkit/learning/storage.py +560 -0
  37. empathy_llm_toolkit/providers.py +4 -11
  38. empathy_llm_toolkit/security/__init__.py +17 -17
  39. empathy_llm_toolkit/utils/tokens.py +2 -5
  40. empathy_os/__init__.py +202 -70
  41. empathy_os/cache_monitor.py +5 -3
  42. empathy_os/cli/__init__.py +11 -55
  43. empathy_os/cli/__main__.py +29 -15
  44. empathy_os/cli/commands/inspection.py +21 -12
  45. empathy_os/cli/commands/memory.py +4 -12
  46. empathy_os/cli/commands/profiling.py +198 -0
  47. empathy_os/cli/commands/utilities.py +27 -7
  48. empathy_os/cli.py +28 -57
  49. empathy_os/cli_unified.py +525 -1164
  50. empathy_os/cost_tracker.py +9 -3
  51. empathy_os/dashboard/server.py +200 -2
  52. empathy_os/hot_reload/__init__.py +7 -7
  53. empathy_os/hot_reload/config.py +6 -7
  54. empathy_os/hot_reload/integration.py +35 -35
  55. empathy_os/hot_reload/reloader.py +57 -57
  56. empathy_os/hot_reload/watcher.py +28 -28
  57. empathy_os/hot_reload/websocket.py +2 -2
  58. empathy_os/memory/__init__.py +11 -4
  59. empathy_os/memory/claude_memory.py +1 -1
  60. empathy_os/memory/cross_session.py +8 -12
  61. empathy_os/memory/edges.py +6 -6
  62. empathy_os/memory/file_session.py +770 -0
  63. empathy_os/memory/graph.py +30 -30
  64. empathy_os/memory/nodes.py +6 -6
  65. empathy_os/memory/short_term.py +15 -9
  66. empathy_os/memory/unified.py +606 -140
  67. empathy_os/meta_workflows/agent_creator.py +3 -9
  68. empathy_os/meta_workflows/cli_meta_workflows.py +113 -53
  69. empathy_os/meta_workflows/form_engine.py +6 -18
  70. empathy_os/meta_workflows/intent_detector.py +64 -24
  71. empathy_os/meta_workflows/models.py +3 -1
  72. empathy_os/meta_workflows/pattern_learner.py +13 -31
  73. empathy_os/meta_workflows/plan_generator.py +55 -47
  74. empathy_os/meta_workflows/session_context.py +2 -3
  75. empathy_os/meta_workflows/workflow.py +20 -51
  76. empathy_os/models/cli.py +2 -2
  77. empathy_os/models/tasks.py +1 -2
  78. empathy_os/models/telemetry.py +4 -1
  79. empathy_os/models/token_estimator.py +3 -1
  80. empathy_os/monitoring/alerts.py +938 -9
  81. empathy_os/monitoring/alerts_cli.py +346 -183
  82. empathy_os/orchestration/execution_strategies.py +12 -29
  83. empathy_os/orchestration/pattern_learner.py +20 -26
  84. empathy_os/orchestration/real_tools.py +6 -15
  85. empathy_os/platform_utils.py +2 -1
  86. empathy_os/plugins/__init__.py +2 -2
  87. empathy_os/plugins/base.py +64 -64
  88. empathy_os/plugins/registry.py +32 -32
  89. empathy_os/project_index/index.py +49 -15
  90. empathy_os/project_index/models.py +1 -2
  91. empathy_os/project_index/reports.py +1 -1
  92. empathy_os/project_index/scanner.py +1 -0
  93. empathy_os/redis_memory.py +10 -7
  94. empathy_os/resilience/__init__.py +1 -1
  95. empathy_os/resilience/health.py +10 -10
  96. empathy_os/routing/__init__.py +7 -7
  97. empathy_os/routing/chain_executor.py +37 -37
  98. empathy_os/routing/classifier.py +36 -36
  99. empathy_os/routing/smart_router.py +40 -40
  100. empathy_os/routing/{wizard_registry.py → workflow_registry.py} +47 -47
  101. empathy_os/scaffolding/__init__.py +8 -8
  102. empathy_os/scaffolding/__main__.py +1 -1
  103. empathy_os/scaffolding/cli.py +28 -28
  104. empathy_os/socratic/__init__.py +3 -19
  105. empathy_os/socratic/ab_testing.py +25 -36
  106. empathy_os/socratic/blueprint.py +38 -38
  107. empathy_os/socratic/cli.py +34 -20
  108. empathy_os/socratic/collaboration.py +30 -28
  109. empathy_os/socratic/domain_templates.py +9 -1
  110. empathy_os/socratic/embeddings.py +17 -13
  111. empathy_os/socratic/engine.py +135 -70
  112. empathy_os/socratic/explainer.py +70 -60
  113. empathy_os/socratic/feedback.py +24 -19
  114. empathy_os/socratic/forms.py +15 -10
  115. empathy_os/socratic/generator.py +51 -35
  116. empathy_os/socratic/llm_analyzer.py +25 -23
  117. empathy_os/socratic/mcp_server.py +99 -159
  118. empathy_os/socratic/session.py +19 -13
  119. empathy_os/socratic/storage.py +98 -67
  120. empathy_os/socratic/success.py +38 -27
  121. empathy_os/socratic/visual_editor.py +51 -39
  122. empathy_os/socratic/web_ui.py +99 -66
  123. empathy_os/telemetry/cli.py +3 -1
  124. empathy_os/telemetry/usage_tracker.py +1 -3
  125. empathy_os/test_generator/__init__.py +3 -3
  126. empathy_os/test_generator/cli.py +28 -28
  127. empathy_os/test_generator/generator.py +64 -66
  128. empathy_os/test_generator/risk_analyzer.py +11 -11
  129. empathy_os/vscode_bridge 2.py +173 -0
  130. empathy_os/vscode_bridge.py +173 -0
  131. empathy_os/workflows/__init__.py +212 -120
  132. empathy_os/workflows/batch_processing.py +8 -24
  133. empathy_os/workflows/bug_predict.py +1 -1
  134. empathy_os/workflows/code_review.py +20 -5
  135. empathy_os/workflows/code_review_pipeline.py +13 -8
  136. empathy_os/workflows/keyboard_shortcuts/workflow.py +6 -2
  137. empathy_os/workflows/manage_documentation.py +1 -0
  138. empathy_os/workflows/orchestrated_health_check.py +6 -11
  139. empathy_os/workflows/orchestrated_release_prep.py +3 -3
  140. empathy_os/workflows/pr_review.py +18 -10
  141. empathy_os/workflows/progressive/README 2.md +454 -0
  142. empathy_os/workflows/progressive/__init__ 2.py +92 -0
  143. empathy_os/workflows/progressive/__init__.py +2 -12
  144. empathy_os/workflows/progressive/cli 2.py +242 -0
  145. empathy_os/workflows/progressive/cli.py +14 -37
  146. empathy_os/workflows/progressive/core 2.py +488 -0
  147. empathy_os/workflows/progressive/core.py +12 -12
  148. empathy_os/workflows/progressive/orchestrator 2.py +701 -0
  149. empathy_os/workflows/progressive/orchestrator.py +166 -144
  150. empathy_os/workflows/progressive/reports 2.py +528 -0
  151. empathy_os/workflows/progressive/reports.py +22 -31
  152. empathy_os/workflows/progressive/telemetry 2.py +280 -0
  153. empathy_os/workflows/progressive/telemetry.py +8 -14
  154. empathy_os/workflows/progressive/test_gen 2.py +514 -0
  155. empathy_os/workflows/progressive/test_gen.py +29 -48
  156. empathy_os/workflows/progressive/workflow 2.py +628 -0
  157. empathy_os/workflows/progressive/workflow.py +31 -70
  158. empathy_os/workflows/release_prep.py +21 -6
  159. empathy_os/workflows/release_prep_crew.py +1 -0
  160. empathy_os/workflows/secure_release.py +13 -6
  161. empathy_os/workflows/security_audit.py +8 -3
  162. empathy_os/workflows/test_coverage_boost_crew.py +3 -2
  163. empathy_os/workflows/test_maintenance_crew.py +1 -0
  164. empathy_os/workflows/test_runner.py +16 -12
  165. empathy_software_plugin/SOFTWARE_PLUGIN_README.md +25 -703
  166. empathy_software_plugin/cli.py +0 -122
  167. patterns/README.md +119 -0
  168. patterns/__init__.py +95 -0
  169. patterns/behavior.py +298 -0
  170. patterns/code_review_memory.json +441 -0
  171. patterns/core.py +97 -0
  172. patterns/debugging.json +3763 -0
  173. patterns/empathy.py +268 -0
  174. patterns/health_check_memory.json +505 -0
  175. patterns/input.py +161 -0
  176. patterns/memory_graph.json +8 -0
  177. patterns/refactoring_memory.json +1113 -0
  178. patterns/registry.py +663 -0
  179. patterns/security_memory.json +8 -0
  180. patterns/structural.py +415 -0
  181. patterns/validation.py +194 -0
  182. coach_wizards/__init__.py +0 -45
  183. coach_wizards/accessibility_wizard.py +0 -91
  184. coach_wizards/api_wizard.py +0 -91
  185. coach_wizards/base_wizard.py +0 -209
  186. coach_wizards/cicd_wizard.py +0 -91
  187. coach_wizards/code_reviewer_README.md +0 -60
  188. coach_wizards/code_reviewer_wizard.py +0 -180
  189. coach_wizards/compliance_wizard.py +0 -91
  190. coach_wizards/database_wizard.py +0 -91
  191. coach_wizards/debugging_wizard.py +0 -91
  192. coach_wizards/documentation_wizard.py +0 -91
  193. coach_wizards/generate_wizards.py +0 -347
  194. coach_wizards/localization_wizard.py +0 -173
  195. coach_wizards/migration_wizard.py +0 -91
  196. coach_wizards/monitoring_wizard.py +0 -91
  197. coach_wizards/observability_wizard.py +0 -91
  198. coach_wizards/performance_wizard.py +0 -91
  199. coach_wizards/prompt_engineering_wizard.py +0 -661
  200. coach_wizards/refactoring_wizard.py +0 -91
  201. coach_wizards/scaling_wizard.py +0 -90
  202. coach_wizards/security_wizard.py +0 -92
  203. coach_wizards/testing_wizard.py +0 -91
  204. empathy_framework-4.6.6.dist-info/METADATA +0 -1597
  205. empathy_framework-4.6.6.dist-info/RECORD +0 -410
  206. empathy_llm_toolkit/wizards/__init__.py +0 -43
  207. empathy_llm_toolkit/wizards/base_wizard.py +0 -364
  208. empathy_llm_toolkit/wizards/customer_support_wizard.py +0 -190
  209. empathy_llm_toolkit/wizards/healthcare_wizard.py +0 -378
  210. empathy_llm_toolkit/wizards/patient_assessment_README.md +0 -64
  211. empathy_llm_toolkit/wizards/patient_assessment_wizard.py +0 -193
  212. empathy_llm_toolkit/wizards/technology_wizard.py +0 -209
  213. empathy_os/wizard_factory_cli.py +0 -170
  214. empathy_software_plugin/wizards/__init__.py +0 -42
  215. empathy_software_plugin/wizards/advanced_debugging_wizard.py +0 -395
  216. empathy_software_plugin/wizards/agent_orchestration_wizard.py +0 -511
  217. empathy_software_plugin/wizards/ai_collaboration_wizard.py +0 -503
  218. empathy_software_plugin/wizards/ai_context_wizard.py +0 -441
  219. empathy_software_plugin/wizards/ai_documentation_wizard.py +0 -503
  220. empathy_software_plugin/wizards/base_wizard.py +0 -288
  221. empathy_software_plugin/wizards/book_chapter_wizard.py +0 -519
  222. empathy_software_plugin/wizards/code_review_wizard.py +0 -604
  223. empathy_software_plugin/wizards/debugging/__init__.py +0 -50
  224. empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +0 -414
  225. empathy_software_plugin/wizards/debugging/config_loaders.py +0 -446
  226. empathy_software_plugin/wizards/debugging/fix_applier.py +0 -469
  227. empathy_software_plugin/wizards/debugging/language_patterns.py +0 -385
  228. empathy_software_plugin/wizards/debugging/linter_parsers.py +0 -470
  229. empathy_software_plugin/wizards/debugging/verification.py +0 -369
  230. empathy_software_plugin/wizards/enhanced_testing_wizard.py +0 -537
  231. empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +0 -816
  232. empathy_software_plugin/wizards/multi_model_wizard.py +0 -501
  233. empathy_software_plugin/wizards/pattern_extraction_wizard.py +0 -422
  234. empathy_software_plugin/wizards/pattern_retriever_wizard.py +0 -400
  235. empathy_software_plugin/wizards/performance/__init__.py +0 -9
  236. empathy_software_plugin/wizards/performance/bottleneck_detector.py +0 -221
  237. empathy_software_plugin/wizards/performance/profiler_parsers.py +0 -278
  238. empathy_software_plugin/wizards/performance/trajectory_analyzer.py +0 -429
  239. empathy_software_plugin/wizards/performance_profiling_wizard.py +0 -305
  240. empathy_software_plugin/wizards/prompt_engineering_wizard.py +0 -425
  241. empathy_software_plugin/wizards/rag_pattern_wizard.py +0 -461
  242. empathy_software_plugin/wizards/security/__init__.py +0 -32
  243. empathy_software_plugin/wizards/security/exploit_analyzer.py +0 -290
  244. empathy_software_plugin/wizards/security/owasp_patterns.py +0 -241
  245. empathy_software_plugin/wizards/security/vulnerability_scanner.py +0 -604
  246. empathy_software_plugin/wizards/security_analysis_wizard.py +0 -322
  247. empathy_software_plugin/wizards/security_learning_wizard.py +0 -740
  248. empathy_software_plugin/wizards/tech_debt_wizard.py +0 -726
  249. empathy_software_plugin/wizards/testing/__init__.py +0 -27
  250. empathy_software_plugin/wizards/testing/coverage_analyzer.py +0 -459
  251. empathy_software_plugin/wizards/testing/quality_analyzer.py +0 -525
  252. empathy_software_plugin/wizards/testing/test_suggester.py +0 -533
  253. empathy_software_plugin/wizards/testing_wizard.py +0 -274
  254. wizards/__init__.py +0 -82
  255. wizards/admission_assessment_wizard.py +0 -644
  256. wizards/care_plan.py +0 -321
  257. wizards/clinical_assessment.py +0 -769
  258. wizards/discharge_planning.py +0 -77
  259. wizards/discharge_summary_wizard.py +0 -468
  260. wizards/dosage_calculation.py +0 -497
  261. wizards/incident_report_wizard.py +0 -454
  262. wizards/medication_reconciliation.py +0 -85
  263. wizards/nursing_assessment.py +0 -171
  264. wizards/patient_education.py +0 -654
  265. wizards/quality_improvement.py +0 -705
  266. wizards/sbar_report.py +0 -324
  267. wizards/sbar_wizard.py +0 -608
  268. wizards/shift_handoff_wizard.py +0 -535
  269. wizards/soap_note_wizard.py +0 -679
  270. wizards/treatment_plan.py +0 -15
  271. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/WHEEL +0 -0
  272. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/entry_points.txt +0 -0
  273. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/licenses/LICENSE +0 -0
@@ -257,9 +257,7 @@ class WorkflowReference:
257
257
  def __post_init__(self):
258
258
  """Validate that exactly one reference type is provided."""
259
259
  if bool(self.workflow_id) == bool(self.inline):
260
- raise ValueError(
261
- "WorkflowReference must have exactly one of: workflow_id or inline"
262
- )
260
+ raise ValueError("WorkflowReference must have exactly one of: workflow_id or inline")
263
261
 
264
262
 
265
263
  @dataclass
@@ -415,8 +413,7 @@ def get_workflow(workflow_id: str) -> WorkflowDefinition:
415
413
  """
416
414
  if workflow_id not in WORKFLOW_REGISTRY:
417
415
  raise ValueError(
418
- f"Unknown workflow: {workflow_id}. "
419
- f"Available: {list(WORKFLOW_REGISTRY.keys())}"
416
+ f"Unknown workflow: {workflow_id}. Available: {list(WORKFLOW_REGISTRY.keys())}"
420
417
  )
421
418
  return WORKFLOW_REGISTRY[workflow_id]
422
419
 
@@ -530,9 +527,7 @@ class ConditionEvaluator:
530
527
 
531
528
  return current
532
529
 
533
- def _evaluate_natural_language(
534
- self, condition_text: str, context: dict[str, Any]
535
- ) -> bool:
530
+ def _evaluate_natural_language(self, condition_text: str, context: dict[str, Any]) -> bool:
536
531
  """Evaluate natural language condition using LLM.
537
532
 
538
533
  Args:
@@ -617,9 +612,7 @@ Respond with ONLY "TRUE" or "FALSE" (no explanation)."""
617
612
  result = match_ratio > 0.5
618
613
  return not result if is_negated else result
619
614
 
620
- def _evaluate_composite(
621
- self, predicate: dict[str, Any], context: dict[str, Any]
622
- ) -> bool:
615
+ def _evaluate_composite(self, predicate: dict[str, Any], context: dict[str, Any]) -> bool:
623
616
  """Evaluate composite condition (AND/OR of other conditions).
624
617
 
625
618
  Args:
@@ -1159,7 +1152,7 @@ class RefinementStrategy(ExecutionStrategy):
1159
1152
  total_duration = 0.0
1160
1153
 
1161
1154
  for i, agent in enumerate(agents):
1162
- stage_name = f"stage_{i+1}"
1155
+ stage_name = f"stage_{i + 1}"
1163
1156
  logger.info(f"Refinement {stage_name}: {agent.id}")
1164
1157
 
1165
1158
  result = await self._execute_agent(agent, current_context)
@@ -1171,7 +1164,7 @@ class RefinementStrategy(ExecutionStrategy):
1171
1164
  current_context[f"{stage_name}_output"] = result.output
1172
1165
  current_context["previous_output"] = result.output
1173
1166
  else:
1174
- logger.error(f"Refinement stage {i+1} failed: {result.error}")
1167
+ logger.error(f"Refinement stage {i + 1} failed: {result.error}")
1175
1168
  break # Stop refinement on failure
1176
1169
 
1177
1170
  # Final output is from last successful stage
@@ -1303,9 +1296,7 @@ class ConditionalStrategy(ExecutionStrategy):
1303
1296
  self.else_branch = else_branch
1304
1297
  self.evaluator = ConditionEvaluator()
1305
1298
 
1306
- async def execute(
1307
- self, agents: list[AgentTemplate], context: dict[str, Any]
1308
- ) -> StrategyResult:
1299
+ async def execute(self, agents: list[AgentTemplate], context: dict[str, Any]) -> StrategyResult:
1309
1300
  """Execute conditional branching."""
1310
1301
  logger.info(f"Conditional: Evaluating '{self.condition.description or 'condition'}'")
1311
1302
 
@@ -1353,9 +1344,7 @@ class MultiConditionalStrategy(ExecutionStrategy):
1353
1344
  self.default_branch = default_branch
1354
1345
  self.evaluator = ConditionEvaluator()
1355
1346
 
1356
- async def execute(
1357
- self, agents: list[AgentTemplate], context: dict[str, Any]
1358
- ) -> StrategyResult:
1347
+ async def execute(self, agents: list[AgentTemplate], context: dict[str, Any]) -> StrategyResult:
1359
1348
  """Execute multi-conditional branching."""
1360
1349
  for i, (condition, branch) in enumerate(self.conditions):
1361
1350
  if self.evaluator.evaluate(condition, context):
@@ -1427,9 +1416,7 @@ class NestedStrategy(ExecutionStrategy):
1427
1416
  self.workflow_ref = workflow_ref
1428
1417
  self.max_depth = max_depth
1429
1418
 
1430
- async def execute(
1431
- self, agents: list[AgentTemplate], context: dict[str, Any]
1432
- ) -> StrategyResult:
1419
+ async def execute(self, agents: list[AgentTemplate], context: dict[str, Any]) -> StrategyResult:
1433
1420
  """Execute nested workflow.
1434
1421
 
1435
1422
  Args:
@@ -1471,9 +1458,7 @@ class NestedStrategy(ExecutionStrategy):
1471
1458
  logger.error(error_msg)
1472
1459
  raise RecursionError(error_msg)
1473
1460
 
1474
- logger.info(
1475
- f"Nested: Entering '{workflow_id}' at depth {nesting.current_depth + 1}"
1476
- )
1461
+ logger.info(f"Nested: Entering '{workflow_id}' at depth {nesting.current_depth + 1}")
1477
1462
 
1478
1463
  # Create child context with updated nesting
1479
1464
  child_nesting = nesting.enter(workflow_id)
@@ -1529,9 +1514,7 @@ class NestedSequentialStrategy(ExecutionStrategy):
1529
1514
  self.steps = steps
1530
1515
  self.max_depth = max_depth
1531
1516
 
1532
- async def execute(
1533
- self, agents: list[AgentTemplate], context: dict[str, Any]
1534
- ) -> StrategyResult:
1517
+ async def execute(self, agents: list[AgentTemplate], context: dict[str, Any]) -> StrategyResult:
1535
1518
  """Execute steps sequentially, handling both agents and nested workflows."""
1536
1519
  if not self.steps:
1537
1520
  raise ValueError("steps list cannot be empty")
@@ -1640,7 +1623,7 @@ def get_strategy(strategy_name: str) -> ExecutionStrategy:
1640
1623
  """
1641
1624
  if strategy_name not in STRATEGY_REGISTRY:
1642
1625
  raise ValueError(
1643
- f"Unknown strategy: {strategy_name}. " f"Available: {list(STRATEGY_REGISTRY.keys())}"
1626
+ f"Unknown strategy: {strategy_name}. Available: {list(STRATEGY_REGISTRY.keys())}"
1644
1627
  )
1645
1628
 
1646
1629
  strategy_class = STRATEGY_REGISTRY[strategy_name]
@@ -17,6 +17,7 @@ Security:
17
17
  import json
18
18
  import logging
19
19
  from collections import defaultdict
20
+ from collections.abc import Iterator
20
21
  from dataclasses import asdict, dataclass, field
21
22
  from datetime import datetime
22
23
  from pathlib import Path
@@ -121,9 +122,7 @@ class PatternStats:
121
122
 
122
123
  # Running average for confidence
123
124
  n = self.total_executions
124
- self.avg_confidence = (
125
- (self.avg_confidence * (n - 1) + record.confidence) / n
126
- )
125
+ self.avg_confidence = (self.avg_confidence * (n - 1) + record.confidence) / n
127
126
 
128
127
  def to_dict(self) -> dict[str, Any]:
129
128
  """Convert to dictionary for serialization."""
@@ -289,21 +288,14 @@ class LearningStore:
289
288
  data = json.load(f)
290
289
 
291
290
  # Load records
292
- self._records = [
293
- ExecutionRecord.from_dict(r) for r in data.get("records", [])
294
- ]
291
+ self._records = [ExecutionRecord.from_dict(r) for r in data.get("records", [])]
295
292
 
296
293
  # Load stats
297
- self._stats = {
298
- s["pattern"]: PatternStats.from_dict(s)
299
- for s in data.get("stats", [])
300
- }
294
+ self._stats = {s["pattern"]: PatternStats.from_dict(s) for s in data.get("stats", [])}
301
295
 
302
296
  # Rebuild context index
303
297
  for i, record in enumerate(self._records):
304
- sig = ContextSignature(
305
- task_type=record.context_features.get("task_type", "")
306
- )
298
+ sig = ContextSignature(task_type=record.context_features.get("task_type", ""))
307
299
  self._context_index[sig.task_type].append(i)
308
300
 
309
301
  logger.info(
@@ -376,14 +368,22 @@ class LearningStore:
376
368
  """
377
369
  return self._stats.get(pattern)
378
370
 
371
+ def iter_all_stats(self) -> Iterator[PatternStats]:
372
+ """Iterate over all pattern statistics (memory-efficient).
373
+
374
+ Yields patterns in arbitrary order. For sorted results,
375
+ use get_all_stats().
376
+ """
377
+ yield from self._stats.values()
378
+
379
379
  def get_all_stats(self) -> list[PatternStats]:
380
- """Get all pattern statistics.
380
+ """Get all pattern statistics sorted by success rate.
381
381
 
382
- Returns:
383
- List of PatternStats sorted by success rate
382
+ Note: For large pattern sets, prefer iter_all_stats() when
383
+ you don't need sorted results.
384
384
  """
385
385
  return sorted(
386
- self._stats.values(),
386
+ self.iter_all_stats(),
387
387
  key=lambda s: s.success_rate,
388
388
  reverse=True,
389
389
  )
@@ -457,9 +457,7 @@ class PatternRecommender:
457
457
  """
458
458
  self.store = store
459
459
 
460
- def recommend(
461
- self, context: dict[str, Any], top_k: int = 3
462
- ) -> list[PatternRecommendation]:
460
+ def recommend(self, context: dict[str, Any], top_k: int = 3) -> list[PatternRecommendation]:
463
461
  """Recommend patterns for a context.
464
462
 
465
463
  Uses hybrid approach:
@@ -516,9 +514,7 @@ class PatternRecommender:
516
514
  recommendations = []
517
515
  for pattern, scores in pattern_scores.items():
518
516
  if scores["total_similarity"] > 0:
519
- weighted_success = (
520
- scores["success_similarity"] / scores["total_similarity"]
521
- )
517
+ weighted_success = scores["success_similarity"] / scores["total_similarity"]
522
518
  stats = self.store.get_stats(pattern)
523
519
 
524
520
  recommendations.append(
@@ -626,9 +622,7 @@ class PatternLearner:
626
622
  self.store.add_record(record)
627
623
  logger.debug(f"Recorded {pattern} execution: success={success}")
628
624
 
629
- def recommend(
630
- self, context: dict[str, Any], top_k: int = 3
631
- ) -> list[PatternRecommendation]:
625
+ def recommend(self, context: dict[str, Any], top_k: int = 3) -> list[PatternRecommendation]:
632
626
  """Get pattern recommendations for a context.
633
627
 
634
628
  Args:
@@ -98,9 +98,7 @@ class RealCoverageAnalyzer:
98
98
  file_age = time.time() - coverage_file.stat().st_mtime
99
99
  # Use existing file if less than 1 hour old
100
100
  if file_age < 3600:
101
- logger.info(
102
- f"Using existing coverage data (age: {file_age/60:.1f} minutes)"
103
- )
101
+ logger.info(f"Using existing coverage data (age: {file_age / 60:.1f} minutes)")
104
102
  else:
105
103
  logger.info("Existing coverage data is stale, regenerating")
106
104
  use_existing = False
@@ -230,6 +228,7 @@ class RealTestGenerator:
230
228
  # Try to load .env file
231
229
  try:
232
230
  from dotenv import load_dotenv
231
+
233
232
  load_dotenv()
234
233
  except ImportError:
235
234
  pass # python-dotenv not required
@@ -254,9 +253,7 @@ class RealTestGenerator:
254
253
  logger.warning(f"Failed to initialize LLM: {e}. Falling back to templates")
255
254
  self.use_llm = False
256
255
 
257
- def generate_tests_for_file(
258
- self, source_file: str, missing_lines: list[int]
259
- ) -> Path:
256
+ def generate_tests_for_file(self, source_file: str, missing_lines: list[int]) -> Path:
260
257
  """Generate tests for uncovered code in a file.
261
258
 
262
259
  Args:
@@ -294,9 +291,7 @@ class RealTestGenerator:
294
291
  if self.use_llm and self._llm:
295
292
  test_code = self._generate_llm_tests(source_file, source_code, missing_lines)
296
293
  else:
297
- test_code = self._generate_basic_test_template(
298
- source_file, source_code, missing_lines
299
- )
294
+ test_code = self._generate_basic_test_template(source_file, source_code, missing_lines)
300
295
 
301
296
  # Write test file
302
297
  validated_path = _validate_file_path(str(test_path))
@@ -423,9 +418,7 @@ Return ONLY the Python test code, starting with imports. No markdown, no explana
423
418
 
424
419
  except Exception as e:
425
420
  logger.error(f"LLM test generation failed: {e}, falling back to template")
426
- return self._generate_basic_test_template(
427
- source_file, source_code, missing_lines
428
- )
421
+ return self._generate_basic_test_template(source_file, source_code, missing_lines)
429
422
 
430
423
  def _extract_api_docs(self, source_code: str) -> str:
431
424
  """Extract API signatures from source code using AST.
@@ -808,9 +801,7 @@ class RealCodeQualityAnalyzer:
808
801
  )
809
802
 
810
803
  # Count error lines
811
- error_count = sum(
812
- 1 for line in result.stdout.split("\n") if ": error:" in line
813
- )
804
+ error_count = sum(1 for line in result.stdout.split("\n") if ": error:" in line)
814
805
  return error_count
815
806
 
816
807
  except FileNotFoundError:
@@ -200,7 +200,8 @@ def write_text_file(path: str | Path, content: str, encoding: str = "utf-8") ->
200
200
 
201
201
  """
202
202
  validated_path = _validate_file_path(str(path))
203
- return validated_path.write_text(content, encoding=encoding)
203
+ result: int = validated_path.write_text(content, encoding=encoding)
204
+ return result
204
205
 
205
206
 
206
207
  def normalize_path(path: str | Path) -> Path:
@@ -8,7 +8,7 @@ Licensed under Fair Source 0.9
8
8
 
9
9
  from .base import (
10
10
  BasePlugin,
11
- BaseWizard,
11
+ BaseWorkflow,
12
12
  PluginError,
13
13
  PluginLoadError,
14
14
  PluginMetadata,
@@ -18,7 +18,7 @@ from .registry import PluginRegistry, get_global_registry
18
18
 
19
19
  __all__ = [
20
20
  "BasePlugin",
21
- "BaseWizard",
21
+ "BaseWorkflow",
22
22
  "PluginError",
23
23
  "PluginLoadError",
24
24
  "PluginMetadata",
@@ -30,25 +30,25 @@ class PluginMetadata:
30
30
  dependencies: list[str] | None = None # Additional package dependencies
31
31
 
32
32
 
33
- class BaseWizard(ABC):
34
- """Universal base class for all wizards across all domains.
33
+ class BaseWorkflow(ABC):
34
+ """Universal base class for all workflows across all domains.
35
35
 
36
- This replaces domain-specific base classes (BaseCoachWizard, etc.)
36
+ This replaces domain-specific base classes (BaseCoachWorkflow, etc.)
37
37
  to provide a unified interface.
38
38
 
39
39
  Design Philosophy:
40
40
  - Domain-agnostic: Works for software, healthcare, finance, etc.
41
- - Level-aware: Each wizard declares its empathy level
42
- - Pattern-contributing: Wizards share learnings via pattern library
41
+ - Level-aware: Each workflow declares its empathy level
42
+ - Pattern-contributing: Workflows share learnings via pattern library
43
43
  """
44
44
 
45
45
  def __init__(self, name: str, domain: str, empathy_level: int, category: str | None = None):
46
- """Initialize a wizard
46
+ """Initialize a workflow
47
47
 
48
48
  Args:
49
- name: Human-readable wizard name
50
- domain: Domain this wizard belongs to (e.g., 'software', 'healthcare')
51
- empathy_level: Which empathy level this wizard operates at (1-5)
49
+ name: Human-readable workflow name
50
+ domain: Domain this workflow belongs to (e.g., 'software', 'healthcare')
51
+ empathy_level: Which empathy level this workflow operates at (1-5)
52
52
  category: Optional category within domain
53
53
 
54
54
  """
@@ -56,16 +56,16 @@ class BaseWizard(ABC):
56
56
  self.domain = domain
57
57
  self.empathy_level = empathy_level
58
58
  self.category = category
59
- self.logger = logging.getLogger(f"wizard.{domain}.{name}")
59
+ self.logger = logging.getLogger(f"workflow.{domain}.{name}")
60
60
 
61
61
  @abstractmethod
62
62
  async def analyze(self, context: dict[str, Any]) -> dict[str, Any]:
63
63
  """Analyze the given context and return results.
64
64
 
65
- This is the main entry point for all wizards. The context structure
65
+ This is the main entry point for all workflows. The context structure
66
66
  is domain-specific but the return format should follow a standard pattern.
67
67
  Subclasses must implement domain-specific analysis logic that aligns with
68
- the wizard's empathy level.
68
+ the workflow's empathy level.
69
69
 
70
70
  Args:
71
71
  context: dict[str, Any]
@@ -83,7 +83,7 @@ class BaseWizard(ABC):
83
83
  - 'recommendations': list[dict] - Actionable next steps
84
84
  - 'patterns': list[str] - Patterns detected for the pattern library
85
85
  - 'confidence': float - Confidence score between 0.0 and 1.0
86
- - 'wizard': str - Name of the wizard that performed analysis
86
+ - 'workflow': str - Name of the workflow that performed analysis
87
87
  - 'empathy_level': int - Empathy level of this analysis (1-5)
88
88
  - 'timestamp': str - ISO format timestamp of analysis
89
89
 
@@ -103,9 +103,9 @@ class BaseWizard(ABC):
103
103
 
104
104
  @abstractmethod
105
105
  def get_required_context(self) -> list[str]:
106
- """Declare what context fields this wizard needs.
106
+ """Declare what context fields this workflow needs.
107
107
 
108
- This method defines the contract between the caller and the wizard.
108
+ This method defines the contract between the caller and the workflow.
109
109
  The caller must provide all declared fields before calling analyze().
110
110
  This enables validation via validate_context() and helps with introspection.
111
111
 
@@ -116,9 +116,9 @@ class BaseWizard(ABC):
116
116
  passed to analyze().
117
117
 
118
118
  Examples:
119
- Software wizard returns: ['code', 'file_path', 'language']
120
- Healthcare wizard returns: ['patient_id', 'vitals', 'medications']
121
- Finance wizard returns: ['transactions', 'account_id', 'period']
119
+ Software workflow returns: ['code', 'file_path', 'language']
120
+ Healthcare workflow returns: ['patient_id', 'vitals', 'medications']
121
+ Finance workflow returns: ['transactions', 'account_id', 'period']
122
122
 
123
123
  Note:
124
124
  - Must return at least one field (even if minimal)
@@ -143,12 +143,12 @@ class BaseWizard(ABC):
143
143
  missing = [key for key in required if key not in context]
144
144
 
145
145
  if missing:
146
- raise ValueError(f"Wizard '{self.name}' missing required context: {missing}")
146
+ raise ValueError(f"Workflow '{self.name}' missing required context: {missing}")
147
147
 
148
148
  return True
149
149
 
150
150
  def get_empathy_level(self) -> int:
151
- """Get the empathy level this wizard operates at"""
151
+ """Get the empathy level this workflow operates at"""
152
152
  return self.empathy_level
153
153
 
154
154
  def contribute_patterns(self, analysis_result: dict[str, Any]) -> dict[str, Any]:
@@ -165,7 +165,7 @@ class BaseWizard(ABC):
165
165
  """
166
166
  # Default implementation - override for custom pattern extraction
167
167
  return {
168
- "wizard": self.name,
168
+ "workflow": self.name,
169
169
  "domain": self.domain,
170
170
  "timestamp": datetime.now().isoformat(),
171
171
  "patterns": analysis_result.get("patterns", []),
@@ -175,18 +175,18 @@ class BaseWizard(ABC):
175
175
  class BasePlugin(ABC):
176
176
  """Base class for domain plugins.
177
177
 
178
- A plugin is a collection of wizards and patterns for a specific domain.
178
+ A plugin is a collection of workflows and patterns for a specific domain.
179
179
 
180
180
  Example:
181
- - SoftwarePlugin: 16+ coach wizards for code analysis
182
- - HealthcarePlugin: Clinical and compliance wizards
183
- - FinancePlugin: Fraud detection, compliance wizards
181
+ - SoftwarePlugin: 16+ coach workflows for code analysis
182
+ - HealthcarePlugin: Clinical and compliance workflows
183
+ - FinancePlugin: Fraud detection, compliance workflows
184
184
 
185
185
  """
186
186
 
187
187
  def __init__(self):
188
188
  self.logger = logging.getLogger(f"plugin.{self.get_metadata().domain}")
189
- self._wizards: dict[str, type[BaseWizard]] = {}
189
+ self._workflows: dict[str, type[BaseWorkflow]] = {}
190
190
  self._initialized = False
191
191
 
192
192
  @abstractmethod
@@ -220,44 +220,44 @@ class BasePlugin(ABC):
220
220
  """
221
221
 
222
222
  @abstractmethod
223
- def register_wizards(self) -> dict[str, type[BaseWizard]]:
224
- """Register all wizards provided by this plugin.
223
+ def register_workflows(self) -> dict[str, type[BaseWorkflow]]:
224
+ """Register all workflows provided by this plugin.
225
225
 
226
- This method defines all analysis wizards available in this plugin.
227
- Wizards are lazy-instantiated by get_wizard() when first requested.
226
+ This method defines all analysis workflows available in this plugin.
227
+ Workflows are lazy-instantiated by get_workflow() when first requested.
228
228
  This method is called during plugin initialization.
229
229
 
230
230
  Returns:
231
- dict[str, type[BaseWizard]]
232
- Dictionary mapping wizard identifiers to Wizard classes (not instances).
231
+ dict[str, type[BaseWorkflow]]
232
+ Dictionary mapping workflow identifiers to Workflow classes (not instances).
233
233
  Keys should be lowercase, snake_case identifiers. Values should be
234
234
  uninstantiated class references.
235
235
 
236
236
  Returns:
237
- dict[str, type[BaseWizard]]
237
+ dict[str, type[BaseWorkflow]]
238
238
  Mapping structure:
239
239
  {
240
- 'wizard_id': WizardClass,
241
- 'another_wizard': AnotherWizardClass,
240
+ 'workflow_id': WorkflowClass,
241
+ 'another_workflow': AnotherWorkflowClass,
242
242
  ...
243
243
  }
244
244
 
245
245
  Example:
246
246
  Software plugin might return:
247
247
  {
248
- 'security': SecurityWizard,
249
- 'performance': PerformanceWizard,
250
- 'maintainability': MaintainabilityWizard,
251
- 'accessibility': AccessibilityWizard,
248
+ 'security': SecurityWorkflow,
249
+ 'performance': PerformanceWorkflow,
250
+ 'maintainability': MaintainabilityWorkflow,
251
+ 'accessibility': AccessibilityWorkflow,
252
252
  }
253
253
 
254
254
  Note:
255
255
  - Return only the class, not instances (instantiation is lazy)
256
- - Use consistent, descriptive wizard IDs
257
- - All returned classes must be subclasses of BaseWizard
258
- - Can return empty dict {} if plugin provides no wizards initially
256
+ - Use consistent, descriptive workflow IDs
257
+ - All returned classes must be subclasses of BaseWorkflow
258
+ - Can return empty dict {} if plugin provides no workflows initially
259
259
  - Called once during initialization via initialize()
260
- - Framework caches results in self._wizards
260
+ - Framework caches results in self._workflows
261
261
 
262
262
  """
263
263
 
@@ -284,63 +284,63 @@ class BasePlugin(ABC):
284
284
 
285
285
  self.logger.info(f"Initializing plugin: {self.get_metadata().name}")
286
286
 
287
- # Register wizards
288
- self._wizards = self.register_wizards()
287
+ # Register workflows
288
+ self._workflows = self.register_workflows()
289
289
 
290
290
  self.logger.info(
291
- f"Plugin '{self.get_metadata().name}' initialized with {len(self._wizards)} wizards",
291
+ f"Plugin '{self.get_metadata().name}' initialized with {len(self._workflows)} workflows",
292
292
  )
293
293
 
294
294
  self._initialized = True
295
295
 
296
- def get_wizard(self, wizard_id: str) -> type[BaseWizard] | None:
297
- """Get a wizard by ID.
296
+ def get_workflow(self, workflow_id: str) -> type[BaseWorkflow] | None:
297
+ """Get a workflow by ID.
298
298
 
299
299
  Args:
300
- wizard_id: Wizard identifier
300
+ workflow_id: Workflow identifier
301
301
 
302
302
  Returns:
303
- Wizard class or None if not found
303
+ Workflow class or None if not found
304
304
 
305
305
  """
306
306
  if not self._initialized:
307
307
  self.initialize()
308
308
 
309
- return self._wizards.get(wizard_id)
309
+ return self._workflows.get(workflow_id)
310
310
 
311
- def list_wizards(self) -> list[str]:
312
- """List all wizard IDs provided by this plugin.
311
+ def list_workflows(self) -> list[str]:
312
+ """List all workflow IDs provided by this plugin.
313
313
 
314
314
  Returns:
315
- List of wizard identifiers
315
+ List of workflow identifiers
316
316
 
317
317
  """
318
318
  if not self._initialized:
319
319
  self.initialize()
320
320
 
321
- return list(self._wizards.keys())
321
+ return list(self._workflows.keys())
322
322
 
323
- def get_wizard_info(self, wizard_id: str) -> dict[str, Any] | None:
324
- """Get information about a wizard without instantiating it.
323
+ def get_workflow_info(self, workflow_id: str) -> dict[str, Any] | None:
324
+ """Get information about a workflow without instantiating it.
325
325
 
326
326
  Args:
327
- wizard_id: Wizard identifier
327
+ workflow_id: Workflow identifier
328
328
 
329
329
  Returns:
330
- Dictionary with wizard metadata
330
+ Dictionary with workflow metadata
331
331
 
332
332
  """
333
- wizard_class = self.get_wizard(wizard_id)
334
- if not wizard_class:
333
+ workflow_class = self.get_workflow(workflow_id)
334
+ if not workflow_class:
335
335
  return None
336
336
 
337
337
  # Create temporary instance to get metadata
338
- # (wizards should be lightweight to construct)
338
+ # (workflows should be lightweight to construct)
339
339
  # Subclasses provide their own defaults for name, domain, empathy_level
340
- temp_instance = wizard_class() # type: ignore[call-arg]
340
+ temp_instance = workflow_class() # type: ignore[call-arg]
341
341
 
342
342
  return {
343
- "id": wizard_id,
343
+ "id": workflow_id,
344
344
  "name": temp_instance.name,
345
345
  "domain": temp_instance.domain,
346
346
  "empathy_level": temp_instance.empathy_level,