empathy-framework 5.3.0__py3-none-any.whl → 5.4.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.
Files changed (458) hide show
  1. empathy_framework-5.4.0.dist-info/METADATA +47 -0
  2. empathy_framework-5.4.0.dist-info/RECORD +8 -0
  3. {empathy_framework-5.3.0.dist-info → empathy_framework-5.4.0.dist-info}/top_level.txt +0 -1
  4. empathy_healthcare_plugin/__init__.py +12 -11
  5. empathy_llm_toolkit/__init__.py +12 -26
  6. empathy_os/__init__.py +12 -356
  7. empathy_software_plugin/__init__.py +12 -11
  8. empathy_framework-5.3.0.dist-info/METADATA +0 -1026
  9. empathy_framework-5.3.0.dist-info/RECORD +0 -456
  10. empathy_framework-5.3.0.dist-info/entry_points.txt +0 -26
  11. empathy_framework-5.3.0.dist-info/licenses/LICENSE +0 -201
  12. empathy_framework-5.3.0.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +0 -101
  13. empathy_healthcare_plugin/monitors/__init__.py +0 -9
  14. empathy_healthcare_plugin/monitors/clinical_protocol_monitor.py +0 -315
  15. empathy_healthcare_plugin/monitors/monitoring/__init__.py +0 -44
  16. empathy_healthcare_plugin/monitors/monitoring/protocol_checker.py +0 -300
  17. empathy_healthcare_plugin/monitors/monitoring/protocol_loader.py +0 -214
  18. empathy_healthcare_plugin/monitors/monitoring/sensor_parsers.py +0 -306
  19. empathy_healthcare_plugin/monitors/monitoring/trajectory_analyzer.py +0 -389
  20. empathy_healthcare_plugin/protocols/cardiac.json +0 -93
  21. empathy_healthcare_plugin/protocols/post_operative.json +0 -92
  22. empathy_healthcare_plugin/protocols/respiratory.json +0 -92
  23. empathy_healthcare_plugin/protocols/sepsis.json +0 -141
  24. empathy_llm_toolkit/README.md +0 -553
  25. empathy_llm_toolkit/agent_factory/__init__.py +0 -53
  26. empathy_llm_toolkit/agent_factory/adapters/__init__.py +0 -85
  27. empathy_llm_toolkit/agent_factory/adapters/autogen_adapter.py +0 -312
  28. empathy_llm_toolkit/agent_factory/adapters/crewai_adapter.py +0 -483
  29. empathy_llm_toolkit/agent_factory/adapters/haystack_adapter.py +0 -298
  30. empathy_llm_toolkit/agent_factory/adapters/langchain_adapter.py +0 -362
  31. empathy_llm_toolkit/agent_factory/adapters/langgraph_adapter.py +0 -333
  32. empathy_llm_toolkit/agent_factory/adapters/native.py +0 -228
  33. empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +0 -423
  34. empathy_llm_toolkit/agent_factory/base.py +0 -305
  35. empathy_llm_toolkit/agent_factory/crews/__init__.py +0 -67
  36. empathy_llm_toolkit/agent_factory/crews/code_review.py +0 -1113
  37. empathy_llm_toolkit/agent_factory/crews/health_check.py +0 -1262
  38. empathy_llm_toolkit/agent_factory/crews/refactoring.py +0 -1128
  39. empathy_llm_toolkit/agent_factory/crews/security_audit.py +0 -1018
  40. empathy_llm_toolkit/agent_factory/decorators.py +0 -287
  41. empathy_llm_toolkit/agent_factory/factory.py +0 -558
  42. empathy_llm_toolkit/agent_factory/framework.py +0 -193
  43. empathy_llm_toolkit/agent_factory/memory_integration.py +0 -328
  44. empathy_llm_toolkit/agent_factory/resilient.py +0 -320
  45. empathy_llm_toolkit/agents_md/__init__.py +0 -22
  46. empathy_llm_toolkit/agents_md/loader.py +0 -218
  47. empathy_llm_toolkit/agents_md/parser.py +0 -271
  48. empathy_llm_toolkit/agents_md/registry.py +0 -307
  49. empathy_llm_toolkit/claude_memory.py +0 -466
  50. empathy_llm_toolkit/cli/__init__.py +0 -8
  51. empathy_llm_toolkit/cli/sync_claude.py +0 -487
  52. empathy_llm_toolkit/code_health.py +0 -1313
  53. empathy_llm_toolkit/commands/__init__.py +0 -51
  54. empathy_llm_toolkit/commands/context.py +0 -375
  55. empathy_llm_toolkit/commands/loader.py +0 -301
  56. empathy_llm_toolkit/commands/models.py +0 -231
  57. empathy_llm_toolkit/commands/parser.py +0 -371
  58. empathy_llm_toolkit/commands/registry.py +0 -429
  59. empathy_llm_toolkit/config/__init__.py +0 -29
  60. empathy_llm_toolkit/config/unified.py +0 -291
  61. empathy_llm_toolkit/context/__init__.py +0 -22
  62. empathy_llm_toolkit/context/compaction.py +0 -455
  63. empathy_llm_toolkit/context/manager.py +0 -434
  64. empathy_llm_toolkit/contextual_patterns.py +0 -361
  65. empathy_llm_toolkit/core.py +0 -907
  66. empathy_llm_toolkit/git_pattern_extractor.py +0 -435
  67. empathy_llm_toolkit/hooks/__init__.py +0 -24
  68. empathy_llm_toolkit/hooks/config.py +0 -306
  69. empathy_llm_toolkit/hooks/executor.py +0 -289
  70. empathy_llm_toolkit/hooks/registry.py +0 -302
  71. empathy_llm_toolkit/hooks/scripts/__init__.py +0 -39
  72. empathy_llm_toolkit/hooks/scripts/evaluate_session.py +0 -201
  73. empathy_llm_toolkit/hooks/scripts/first_time_init.py +0 -285
  74. empathy_llm_toolkit/hooks/scripts/pre_compact.py +0 -207
  75. empathy_llm_toolkit/hooks/scripts/session_end.py +0 -183
  76. empathy_llm_toolkit/hooks/scripts/session_start.py +0 -163
  77. empathy_llm_toolkit/hooks/scripts/suggest_compact.py +0 -225
  78. empathy_llm_toolkit/learning/__init__.py +0 -30
  79. empathy_llm_toolkit/learning/evaluator.py +0 -438
  80. empathy_llm_toolkit/learning/extractor.py +0 -514
  81. empathy_llm_toolkit/learning/storage.py +0 -560
  82. empathy_llm_toolkit/levels.py +0 -227
  83. empathy_llm_toolkit/pattern_confidence.py +0 -414
  84. empathy_llm_toolkit/pattern_resolver.py +0 -272
  85. empathy_llm_toolkit/pattern_summary.py +0 -350
  86. empathy_llm_toolkit/providers.py +0 -967
  87. empathy_llm_toolkit/routing/__init__.py +0 -32
  88. empathy_llm_toolkit/routing/model_router.py +0 -362
  89. empathy_llm_toolkit/security/IMPLEMENTATION_SUMMARY.md +0 -413
  90. empathy_llm_toolkit/security/PHASE2_COMPLETE.md +0 -384
  91. empathy_llm_toolkit/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +0 -271
  92. empathy_llm_toolkit/security/QUICK_REFERENCE.md +0 -316
  93. empathy_llm_toolkit/security/README.md +0 -262
  94. empathy_llm_toolkit/security/__init__.py +0 -62
  95. empathy_llm_toolkit/security/audit_logger.py +0 -929
  96. empathy_llm_toolkit/security/audit_logger_example.py +0 -152
  97. empathy_llm_toolkit/security/pii_scrubber.py +0 -640
  98. empathy_llm_toolkit/security/secrets_detector.py +0 -678
  99. empathy_llm_toolkit/security/secrets_detector_example.py +0 -304
  100. empathy_llm_toolkit/security/secure_memdocs.py +0 -1192
  101. empathy_llm_toolkit/security/secure_memdocs_example.py +0 -278
  102. empathy_llm_toolkit/session_status.py +0 -745
  103. empathy_llm_toolkit/state.py +0 -246
  104. empathy_llm_toolkit/utils/__init__.py +0 -5
  105. empathy_llm_toolkit/utils/tokens.py +0 -349
  106. empathy_os/adaptive/__init__.py +0 -13
  107. empathy_os/adaptive/task_complexity.py +0 -127
  108. empathy_os/agent_monitoring.py +0 -414
  109. empathy_os/cache/__init__.py +0 -117
  110. empathy_os/cache/base.py +0 -166
  111. empathy_os/cache/dependency_manager.py +0 -256
  112. empathy_os/cache/hash_only.py +0 -251
  113. empathy_os/cache/hybrid.py +0 -457
  114. empathy_os/cache/storage.py +0 -285
  115. empathy_os/cache_monitor.py +0 -356
  116. empathy_os/cache_stats.py +0 -298
  117. empathy_os/cli/__init__.py +0 -152
  118. empathy_os/cli/__main__.py +0 -12
  119. empathy_os/cli/commands/__init__.py +0 -1
  120. empathy_os/cli/commands/batch.py +0 -264
  121. empathy_os/cli/commands/cache.py +0 -248
  122. empathy_os/cli/commands/help.py +0 -331
  123. empathy_os/cli/commands/info.py +0 -140
  124. empathy_os/cli/commands/inspect.py +0 -436
  125. empathy_os/cli/commands/inspection.py +0 -57
  126. empathy_os/cli/commands/memory.py +0 -48
  127. empathy_os/cli/commands/metrics.py +0 -92
  128. empathy_os/cli/commands/orchestrate.py +0 -184
  129. empathy_os/cli/commands/patterns.py +0 -207
  130. empathy_os/cli/commands/profiling.py +0 -202
  131. empathy_os/cli/commands/provider.py +0 -98
  132. empathy_os/cli/commands/routing.py +0 -285
  133. empathy_os/cli/commands/setup.py +0 -96
  134. empathy_os/cli/commands/status.py +0 -235
  135. empathy_os/cli/commands/sync.py +0 -166
  136. empathy_os/cli/commands/tier.py +0 -121
  137. empathy_os/cli/commands/utilities.py +0 -114
  138. empathy_os/cli/commands/workflow.py +0 -579
  139. empathy_os/cli/core.py +0 -32
  140. empathy_os/cli/parsers/__init__.py +0 -68
  141. empathy_os/cli/parsers/batch.py +0 -118
  142. empathy_os/cli/parsers/cache.py +0 -65
  143. empathy_os/cli/parsers/help.py +0 -41
  144. empathy_os/cli/parsers/info.py +0 -26
  145. empathy_os/cli/parsers/inspect.py +0 -66
  146. empathy_os/cli/parsers/metrics.py +0 -42
  147. empathy_os/cli/parsers/orchestrate.py +0 -61
  148. empathy_os/cli/parsers/patterns.py +0 -54
  149. empathy_os/cli/parsers/provider.py +0 -40
  150. empathy_os/cli/parsers/routing.py +0 -110
  151. empathy_os/cli/parsers/setup.py +0 -42
  152. empathy_os/cli/parsers/status.py +0 -47
  153. empathy_os/cli/parsers/sync.py +0 -31
  154. empathy_os/cli/parsers/tier.py +0 -33
  155. empathy_os/cli/parsers/workflow.py +0 -77
  156. empathy_os/cli/utils/__init__.py +0 -1
  157. empathy_os/cli/utils/data.py +0 -242
  158. empathy_os/cli/utils/helpers.py +0 -68
  159. empathy_os/cli_legacy.py +0 -3957
  160. empathy_os/cli_minimal.py +0 -1159
  161. empathy_os/cli_router.py +0 -437
  162. empathy_os/cli_unified.py +0 -814
  163. empathy_os/config/__init__.py +0 -66
  164. empathy_os/config/xml_config.py +0 -286
  165. empathy_os/config.py +0 -545
  166. empathy_os/coordination.py +0 -870
  167. empathy_os/core.py +0 -1511
  168. empathy_os/core_modules/__init__.py +0 -15
  169. empathy_os/cost_tracker.py +0 -626
  170. empathy_os/dashboard/__init__.py +0 -41
  171. empathy_os/dashboard/app.py +0 -512
  172. empathy_os/dashboard/simple_server.py +0 -435
  173. empathy_os/dashboard/standalone_server.py +0 -547
  174. empathy_os/discovery.py +0 -306
  175. empathy_os/emergence.py +0 -306
  176. empathy_os/exceptions.py +0 -123
  177. empathy_os/feedback_loops.py +0 -373
  178. empathy_os/hot_reload/README.md +0 -473
  179. empathy_os/hot_reload/__init__.py +0 -62
  180. empathy_os/hot_reload/config.py +0 -83
  181. empathy_os/hot_reload/integration.py +0 -229
  182. empathy_os/hot_reload/reloader.py +0 -298
  183. empathy_os/hot_reload/watcher.py +0 -183
  184. empathy_os/hot_reload/websocket.py +0 -177
  185. empathy_os/levels.py +0 -577
  186. empathy_os/leverage_points.py +0 -441
  187. empathy_os/logging_config.py +0 -261
  188. empathy_os/mcp/__init__.py +0 -10
  189. empathy_os/mcp/server.py +0 -506
  190. empathy_os/memory/__init__.py +0 -237
  191. empathy_os/memory/claude_memory.py +0 -469
  192. empathy_os/memory/config.py +0 -224
  193. empathy_os/memory/control_panel.py +0 -1290
  194. empathy_os/memory/control_panel_support.py +0 -145
  195. empathy_os/memory/cross_session.py +0 -845
  196. empathy_os/memory/edges.py +0 -179
  197. empathy_os/memory/encryption.py +0 -159
  198. empathy_os/memory/file_session.py +0 -770
  199. empathy_os/memory/graph.py +0 -570
  200. empathy_os/memory/long_term.py +0 -913
  201. empathy_os/memory/long_term_types.py +0 -99
  202. empathy_os/memory/mixins/__init__.py +0 -25
  203. empathy_os/memory/mixins/backend_init_mixin.py +0 -249
  204. empathy_os/memory/mixins/capabilities_mixin.py +0 -208
  205. empathy_os/memory/mixins/handoff_mixin.py +0 -208
  206. empathy_os/memory/mixins/lifecycle_mixin.py +0 -49
  207. empathy_os/memory/mixins/long_term_mixin.py +0 -352
  208. empathy_os/memory/mixins/promotion_mixin.py +0 -109
  209. empathy_os/memory/mixins/short_term_mixin.py +0 -182
  210. empathy_os/memory/nodes.py +0 -179
  211. empathy_os/memory/redis_bootstrap.py +0 -540
  212. empathy_os/memory/security/__init__.py +0 -31
  213. empathy_os/memory/security/audit_logger.py +0 -932
  214. empathy_os/memory/security/pii_scrubber.py +0 -640
  215. empathy_os/memory/security/secrets_detector.py +0 -678
  216. empathy_os/memory/short_term.py +0 -2192
  217. empathy_os/memory/simple_storage.py +0 -302
  218. empathy_os/memory/storage/__init__.py +0 -15
  219. empathy_os/memory/storage_backend.py +0 -167
  220. empathy_os/memory/summary_index.py +0 -583
  221. empathy_os/memory/types.py +0 -446
  222. empathy_os/memory/unified.py +0 -182
  223. empathy_os/meta_workflows/__init__.py +0 -74
  224. empathy_os/meta_workflows/agent_creator.py +0 -248
  225. empathy_os/meta_workflows/builtin_templates.py +0 -567
  226. empathy_os/meta_workflows/cli_commands/__init__.py +0 -56
  227. empathy_os/meta_workflows/cli_commands/agent_commands.py +0 -321
  228. empathy_os/meta_workflows/cli_commands/analytics_commands.py +0 -442
  229. empathy_os/meta_workflows/cli_commands/config_commands.py +0 -232
  230. empathy_os/meta_workflows/cli_commands/memory_commands.py +0 -182
  231. empathy_os/meta_workflows/cli_commands/template_commands.py +0 -354
  232. empathy_os/meta_workflows/cli_commands/workflow_commands.py +0 -382
  233. empathy_os/meta_workflows/cli_meta_workflows.py +0 -59
  234. empathy_os/meta_workflows/form_engine.py +0 -292
  235. empathy_os/meta_workflows/intent_detector.py +0 -409
  236. empathy_os/meta_workflows/models.py +0 -569
  237. empathy_os/meta_workflows/pattern_learner.py +0 -738
  238. empathy_os/meta_workflows/plan_generator.py +0 -384
  239. empathy_os/meta_workflows/session_context.py +0 -397
  240. empathy_os/meta_workflows/template_registry.py +0 -229
  241. empathy_os/meta_workflows/workflow.py +0 -984
  242. empathy_os/metrics/__init__.py +0 -12
  243. empathy_os/metrics/collector.py +0 -31
  244. empathy_os/metrics/prompt_metrics.py +0 -194
  245. empathy_os/models/__init__.py +0 -172
  246. empathy_os/models/__main__.py +0 -13
  247. empathy_os/models/adaptive_routing.py +0 -437
  248. empathy_os/models/auth_cli.py +0 -444
  249. empathy_os/models/auth_strategy.py +0 -450
  250. empathy_os/models/cli.py +0 -655
  251. empathy_os/models/empathy_executor.py +0 -354
  252. empathy_os/models/executor.py +0 -257
  253. empathy_os/models/fallback.py +0 -762
  254. empathy_os/models/provider_config.py +0 -282
  255. empathy_os/models/registry.py +0 -472
  256. empathy_os/models/tasks.py +0 -359
  257. empathy_os/models/telemetry/__init__.py +0 -71
  258. empathy_os/models/telemetry/analytics.py +0 -594
  259. empathy_os/models/telemetry/backend.py +0 -196
  260. empathy_os/models/telemetry/data_models.py +0 -431
  261. empathy_os/models/telemetry/storage.py +0 -489
  262. empathy_os/models/token_estimator.py +0 -420
  263. empathy_os/models/validation.py +0 -280
  264. empathy_os/monitoring/__init__.py +0 -52
  265. empathy_os/monitoring/alerts.py +0 -946
  266. empathy_os/monitoring/alerts_cli.py +0 -448
  267. empathy_os/monitoring/multi_backend.py +0 -271
  268. empathy_os/monitoring/otel_backend.py +0 -362
  269. empathy_os/optimization/__init__.py +0 -19
  270. empathy_os/optimization/context_optimizer.py +0 -272
  271. empathy_os/orchestration/__init__.py +0 -67
  272. empathy_os/orchestration/agent_templates.py +0 -707
  273. empathy_os/orchestration/config_store.py +0 -499
  274. empathy_os/orchestration/execution_strategies.py +0 -2111
  275. empathy_os/orchestration/meta_orchestrator.py +0 -1168
  276. empathy_os/orchestration/pattern_learner.py +0 -696
  277. empathy_os/orchestration/real_tools.py +0 -931
  278. empathy_os/pattern_cache.py +0 -187
  279. empathy_os/pattern_library.py +0 -542
  280. empathy_os/patterns/debugging/all_patterns.json +0 -81
  281. empathy_os/patterns/debugging/workflow_20260107_1770825e.json +0 -77
  282. empathy_os/patterns/refactoring_memory.json +0 -89
  283. empathy_os/persistence.py +0 -564
  284. empathy_os/platform_utils.py +0 -265
  285. empathy_os/plugins/__init__.py +0 -28
  286. empathy_os/plugins/base.py +0 -361
  287. empathy_os/plugins/registry.py +0 -268
  288. empathy_os/project_index/__init__.py +0 -32
  289. empathy_os/project_index/cli.py +0 -335
  290. empathy_os/project_index/index.py +0 -667
  291. empathy_os/project_index/models.py +0 -504
  292. empathy_os/project_index/reports.py +0 -474
  293. empathy_os/project_index/scanner.py +0 -777
  294. empathy_os/project_index/scanner_parallel.py +0 -291
  295. empathy_os/prompts/__init__.py +0 -61
  296. empathy_os/prompts/config.py +0 -77
  297. empathy_os/prompts/context.py +0 -177
  298. empathy_os/prompts/parser.py +0 -285
  299. empathy_os/prompts/registry.py +0 -313
  300. empathy_os/prompts/templates.py +0 -208
  301. empathy_os/redis_config.py +0 -302
  302. empathy_os/redis_memory.py +0 -799
  303. empathy_os/resilience/__init__.py +0 -56
  304. empathy_os/resilience/circuit_breaker.py +0 -256
  305. empathy_os/resilience/fallback.py +0 -179
  306. empathy_os/resilience/health.py +0 -300
  307. empathy_os/resilience/retry.py +0 -209
  308. empathy_os/resilience/timeout.py +0 -135
  309. empathy_os/routing/__init__.py +0 -43
  310. empathy_os/routing/chain_executor.py +0 -433
  311. empathy_os/routing/classifier.py +0 -217
  312. empathy_os/routing/smart_router.py +0 -234
  313. empathy_os/routing/workflow_registry.py +0 -343
  314. empathy_os/scaffolding/README.md +0 -589
  315. empathy_os/scaffolding/__init__.py +0 -35
  316. empathy_os/scaffolding/__main__.py +0 -14
  317. empathy_os/scaffolding/cli.py +0 -240
  318. empathy_os/socratic/__init__.py +0 -256
  319. empathy_os/socratic/ab_testing.py +0 -958
  320. empathy_os/socratic/blueprint.py +0 -533
  321. empathy_os/socratic/cli.py +0 -703
  322. empathy_os/socratic/collaboration.py +0 -1114
  323. empathy_os/socratic/domain_templates.py +0 -924
  324. empathy_os/socratic/embeddings.py +0 -738
  325. empathy_os/socratic/engine.py +0 -794
  326. empathy_os/socratic/explainer.py +0 -682
  327. empathy_os/socratic/feedback.py +0 -772
  328. empathy_os/socratic/forms.py +0 -629
  329. empathy_os/socratic/generator.py +0 -732
  330. empathy_os/socratic/llm_analyzer.py +0 -637
  331. empathy_os/socratic/mcp_server.py +0 -702
  332. empathy_os/socratic/session.py +0 -312
  333. empathy_os/socratic/storage.py +0 -667
  334. empathy_os/socratic/success.py +0 -730
  335. empathy_os/socratic/visual_editor.py +0 -860
  336. empathy_os/socratic/web_ui.py +0 -958
  337. empathy_os/telemetry/__init__.py +0 -39
  338. empathy_os/telemetry/agent_coordination.py +0 -475
  339. empathy_os/telemetry/agent_tracking.py +0 -367
  340. empathy_os/telemetry/approval_gates.py +0 -545
  341. empathy_os/telemetry/cli.py +0 -1231
  342. empathy_os/telemetry/commands/__init__.py +0 -14
  343. empathy_os/telemetry/commands/dashboard_commands.py +0 -696
  344. empathy_os/telemetry/event_streaming.py +0 -409
  345. empathy_os/telemetry/feedback_loop.py +0 -567
  346. empathy_os/telemetry/usage_tracker.py +0 -591
  347. empathy_os/templates.py +0 -754
  348. empathy_os/test_generator/__init__.py +0 -38
  349. empathy_os/test_generator/__main__.py +0 -14
  350. empathy_os/test_generator/cli.py +0 -234
  351. empathy_os/test_generator/generator.py +0 -355
  352. empathy_os/test_generator/risk_analyzer.py +0 -216
  353. empathy_os/tier_recommender.py +0 -384
  354. empathy_os/tools.py +0 -183
  355. empathy_os/trust/__init__.py +0 -28
  356. empathy_os/trust/circuit_breaker.py +0 -579
  357. empathy_os/trust_building.py +0 -527
  358. empathy_os/validation/__init__.py +0 -19
  359. empathy_os/validation/xml_validator.py +0 -281
  360. empathy_os/vscode_bridge.py +0 -173
  361. empathy_os/workflow_commands.py +0 -780
  362. empathy_os/workflow_patterns/__init__.py +0 -33
  363. empathy_os/workflow_patterns/behavior.py +0 -249
  364. empathy_os/workflow_patterns/core.py +0 -76
  365. empathy_os/workflow_patterns/output.py +0 -99
  366. empathy_os/workflow_patterns/registry.py +0 -255
  367. empathy_os/workflow_patterns/structural.py +0 -288
  368. empathy_os/workflows/__init__.py +0 -539
  369. empathy_os/workflows/autonomous_test_gen.py +0 -1268
  370. empathy_os/workflows/base.py +0 -2667
  371. empathy_os/workflows/batch_processing.py +0 -342
  372. empathy_os/workflows/bug_predict.py +0 -1084
  373. empathy_os/workflows/builder.py +0 -273
  374. empathy_os/workflows/caching.py +0 -253
  375. empathy_os/workflows/code_review.py +0 -1048
  376. empathy_os/workflows/code_review_adapters.py +0 -312
  377. empathy_os/workflows/code_review_pipeline.py +0 -722
  378. empathy_os/workflows/config.py +0 -645
  379. empathy_os/workflows/dependency_check.py +0 -644
  380. empathy_os/workflows/document_gen/__init__.py +0 -25
  381. empathy_os/workflows/document_gen/config.py +0 -30
  382. empathy_os/workflows/document_gen/report_formatter.py +0 -162
  383. empathy_os/workflows/document_gen/workflow.py +0 -1426
  384. empathy_os/workflows/document_manager.py +0 -216
  385. empathy_os/workflows/document_manager_README.md +0 -134
  386. empathy_os/workflows/documentation_orchestrator.py +0 -1205
  387. empathy_os/workflows/history.py +0 -510
  388. empathy_os/workflows/keyboard_shortcuts/__init__.py +0 -39
  389. empathy_os/workflows/keyboard_shortcuts/generators.py +0 -391
  390. empathy_os/workflows/keyboard_shortcuts/parsers.py +0 -416
  391. empathy_os/workflows/keyboard_shortcuts/prompts.py +0 -295
  392. empathy_os/workflows/keyboard_shortcuts/schema.py +0 -193
  393. empathy_os/workflows/keyboard_shortcuts/workflow.py +0 -509
  394. empathy_os/workflows/llm_base.py +0 -363
  395. empathy_os/workflows/manage_docs.py +0 -87
  396. empathy_os/workflows/manage_docs_README.md +0 -134
  397. empathy_os/workflows/manage_documentation.py +0 -821
  398. empathy_os/workflows/new_sample_workflow1.py +0 -149
  399. empathy_os/workflows/new_sample_workflow1_README.md +0 -150
  400. empathy_os/workflows/orchestrated_health_check.py +0 -849
  401. empathy_os/workflows/orchestrated_release_prep.py +0 -600
  402. empathy_os/workflows/output.py +0 -413
  403. empathy_os/workflows/perf_audit.py +0 -863
  404. empathy_os/workflows/pr_review.py +0 -762
  405. empathy_os/workflows/progress.py +0 -785
  406. empathy_os/workflows/progress_server.py +0 -322
  407. empathy_os/workflows/progressive/README 2.md +0 -454
  408. empathy_os/workflows/progressive/README.md +0 -454
  409. empathy_os/workflows/progressive/__init__.py +0 -82
  410. empathy_os/workflows/progressive/cli.py +0 -219
  411. empathy_os/workflows/progressive/core.py +0 -488
  412. empathy_os/workflows/progressive/orchestrator.py +0 -723
  413. empathy_os/workflows/progressive/reports.py +0 -520
  414. empathy_os/workflows/progressive/telemetry.py +0 -274
  415. empathy_os/workflows/progressive/test_gen.py +0 -495
  416. empathy_os/workflows/progressive/workflow.py +0 -589
  417. empathy_os/workflows/refactor_plan.py +0 -694
  418. empathy_os/workflows/release_prep.py +0 -895
  419. empathy_os/workflows/release_prep_crew.py +0 -969
  420. empathy_os/workflows/research_synthesis.py +0 -404
  421. empathy_os/workflows/routing.py +0 -168
  422. empathy_os/workflows/secure_release.py +0 -593
  423. empathy_os/workflows/security_adapters.py +0 -297
  424. empathy_os/workflows/security_audit.py +0 -1329
  425. empathy_os/workflows/security_audit_phase3.py +0 -355
  426. empathy_os/workflows/seo_optimization.py +0 -633
  427. empathy_os/workflows/step_config.py +0 -234
  428. empathy_os/workflows/telemetry_mixin.py +0 -269
  429. empathy_os/workflows/test5.py +0 -125
  430. empathy_os/workflows/test5_README.md +0 -158
  431. empathy_os/workflows/test_coverage_boost_crew.py +0 -849
  432. empathy_os/workflows/test_gen/__init__.py +0 -52
  433. empathy_os/workflows/test_gen/ast_analyzer.py +0 -249
  434. empathy_os/workflows/test_gen/config.py +0 -88
  435. empathy_os/workflows/test_gen/data_models.py +0 -38
  436. empathy_os/workflows/test_gen/report_formatter.py +0 -289
  437. empathy_os/workflows/test_gen/test_templates.py +0 -381
  438. empathy_os/workflows/test_gen/workflow.py +0 -655
  439. empathy_os/workflows/test_gen.py +0 -54
  440. empathy_os/workflows/test_gen_behavioral.py +0 -477
  441. empathy_os/workflows/test_gen_parallel.py +0 -341
  442. empathy_os/workflows/test_lifecycle.py +0 -526
  443. empathy_os/workflows/test_maintenance.py +0 -627
  444. empathy_os/workflows/test_maintenance_cli.py +0 -590
  445. empathy_os/workflows/test_maintenance_crew.py +0 -840
  446. empathy_os/workflows/test_runner.py +0 -622
  447. empathy_os/workflows/tier_tracking.py +0 -531
  448. empathy_os/workflows/xml_enhanced_crew.py +0 -285
  449. empathy_software_plugin/SOFTWARE_PLUGIN_README.md +0 -57
  450. empathy_software_plugin/cli/__init__.py +0 -120
  451. empathy_software_plugin/cli/inspect.py +0 -362
  452. empathy_software_plugin/cli.py +0 -574
  453. empathy_software_plugin/plugin.py +0 -188
  454. workflow_scaffolding/__init__.py +0 -11
  455. workflow_scaffolding/__main__.py +0 -12
  456. workflow_scaffolding/cli.py +0 -206
  457. workflow_scaffolding/generator.py +0 -265
  458. {empathy_framework-5.3.0.dist-info → empathy_framework-5.4.0.dist-info}/WHEEL +0 -0
@@ -1,849 +0,0 @@
1
- """Test Coverage Boost Crew - Multi-agent test generation workflow.
2
-
3
- .. deprecated:: 4.3.0
4
- This workflow is deprecated in favor of the meta-workflow system.
5
- Use ``empathy meta-workflow run test-coverage-boost`` instead.
6
- See docs/CREWAI_MIGRATION.md for migration guide.
7
-
8
- This module provides a CrewAI-based workflow that uses 3 specialized agents
9
- to analyze coverage gaps, generate tests, and validate improvements.
10
-
11
- Copyright 2025 Smart AI Memory, LLC
12
- Licensed under Fair Source 0.9
13
- """
14
-
15
- import asyncio
16
- import json
17
- import re
18
- import warnings
19
- from dataclasses import dataclass, field
20
- from datetime import datetime
21
- from pathlib import Path
22
-
23
- from empathy_os.models.executor import ExecutionContext
24
-
25
-
26
- @dataclass
27
- class Agent:
28
- """Agent configuration for test coverage boost."""
29
-
30
- role: str
31
- goal: str
32
- backstory: str
33
- expertise_level: str = "expert"
34
- weight: float = 1.0
35
-
36
- def get_system_prompt(self) -> str:
37
- """Generate system prompt for this agent."""
38
- return f"""You are a {self.role}.
39
-
40
- {self.backstory}
41
-
42
- Your goal: {self.goal}
43
-
44
- Expertise level: {self.expertise_level}
45
-
46
- Provide your response in this format:
47
- <thinking>
48
- [Your analysis and reasoning]
49
- </thinking>
50
-
51
- <answer>
52
- [Your JSON response matching the expected format]
53
- </answer>"""
54
-
55
-
56
- @dataclass
57
- class Task:
58
- """Task configuration for an agent."""
59
-
60
- description: str
61
- expected_output: str
62
- context_keys: list[str] = field(default_factory=list)
63
-
64
- def get_user_prompt(self, context: dict) -> str:
65
- """Generate user prompt with context data."""
66
- # Build context section
67
- context_lines = ["<context>"]
68
- for key in self.context_keys:
69
- if key in context:
70
- value = context[key]
71
- if isinstance(value, (dict, list)):
72
- value = json.dumps(value, indent=2)
73
- context_lines.append(f"<{key}>")
74
- context_lines.append(str(value))
75
- context_lines.append(f"</{key}>")
76
- context_lines.append("</context>")
77
-
78
- return f"""{self.description}
79
-
80
- {chr(10).join(context_lines)}
81
-
82
- <expected_output>
83
- {self.expected_output}
84
- </expected_output>
85
-
86
- <instructions>
87
- 1. Review all context data in the <context> tags above
88
- 2. Structure your response using <thinking> and <answer> tags
89
- 3. Provide a JSON response in the <answer> section matching the expected output format exactly
90
- </instructions>"""
91
-
92
-
93
- @dataclass
94
- class CoverageGap:
95
- """Represents a gap in test coverage."""
96
-
97
- file_path: str
98
- function_name: str
99
- line_start: int
100
- line_end: int
101
- priority: float # 0-1, higher = more important
102
- reason: str
103
-
104
-
105
- @dataclass
106
- class GeneratedTest:
107
- """Represents a generated test case."""
108
-
109
- test_name: str
110
- test_code: str
111
- target_function: str
112
- target_file: str
113
- coverage_impact: float # Estimated coverage improvement
114
-
115
-
116
- @dataclass
117
- class TestCoverageBoostCrewResult:
118
- """Result from TestCoverageBoostCrew execution."""
119
-
120
- success: bool
121
- current_coverage: float # 0-100
122
- target_coverage: float # 0-100
123
- final_coverage: float # 0-100
124
- coverage_improvement: float # Percentage points gained
125
-
126
- # Detailed results
127
- gaps_found: int
128
- tests_generated: int
129
- tests_passing: int
130
- gaps_analyzed: list[CoverageGap] = field(default_factory=list)
131
- generated_tests: list[GeneratedTest] = field(default_factory=list)
132
-
133
- # Execution metadata
134
- agents_executed: int = 3
135
- cost: float = 0.0
136
- duration_ms: int = 0
137
- timestamp: str = field(default_factory=lambda: datetime.now().isoformat())
138
- errors: list[str] = field(default_factory=list)
139
-
140
-
141
- def parse_xml_response(response: str) -> dict:
142
- """Parse XML-structured agent response."""
143
- result = {
144
- "thinking": "",
145
- "answer": "",
146
- "raw": response,
147
- "has_xml_structure": False,
148
- }
149
-
150
- # Try to extract thinking section
151
- thinking_start = response.find("<thinking>")
152
- thinking_end = response.find("</thinking>")
153
- if thinking_start != -1 and thinking_end != -1:
154
- result["thinking"] = response[thinking_start + 10 : thinking_end].strip()
155
- result["has_xml_structure"] = True
156
-
157
- # Try to extract answer section
158
- answer_start = response.find("<answer>")
159
- answer_end = response.find("</answer>")
160
- if answer_start != -1 and answer_end != -1:
161
- result["answer"] = response[answer_start + 8 : answer_end].strip()
162
- result["has_xml_structure"] = True
163
-
164
- # If no answer found, extract content after </thinking> or use full response
165
- if not result["answer"]:
166
- if thinking_end != -1:
167
- # Extract everything after </thinking> tag
168
- result["answer"] = response[thinking_end + 11 :].strip()
169
- else:
170
- # Use full response as fallback
171
- result["answer"] = response
172
-
173
- return result
174
-
175
-
176
- class TestCoverageBoostCrew:
177
- """Test Coverage Boost Crew - Multi-agent test generation.
178
-
179
- Uses 3 specialized agents to analyze coverage gaps, generate tests,
180
- and validate improvements.
181
-
182
- Agents:
183
- - Gap Analyzer: Identifies untested code and prioritizes gaps
184
- - Test Generator: Creates comprehensive test cases
185
- - Test Validator: Validates generated tests and measures improvement
186
-
187
- Usage:
188
- crew = TestCoverageBoostCrew(target_coverage=85.0)
189
- result = await crew.execute(project_root="./src")
190
-
191
- print(f"Coverage improved by {result.coverage_improvement}%")
192
- """
193
-
194
- name = "Test_Coverage_Boost_Crew"
195
- description = "Multi-agent test generation with gap analysis and validation"
196
- process_type = "sequential"
197
-
198
- def __init__(
199
- self,
200
- target_coverage: float = 80.0,
201
- project_root: str = ".",
202
- **kwargs, # Accept extra CLI arguments
203
- ):
204
- """Initialize the test coverage boost crew.
205
-
206
- .. deprecated:: 4.3.0
207
- Use meta-workflow system instead: ``empathy meta-workflow run test-coverage-boost``
208
-
209
- Args:
210
- target_coverage: Target coverage percentage (0-100)
211
- project_root: Root directory of project to analyze
212
- **kwargs: Additional arguments (ignored, for CLI compatibility)
213
- """
214
- warnings.warn(
215
- "TestCoverageBoostCrew is deprecated since v4.3.0. "
216
- "Use meta-workflow system instead: empathy meta-workflow run test-coverage-boost. "
217
- "See docs/CREWAI_MIGRATION.md for migration guide.",
218
- DeprecationWarning,
219
- stacklevel=2,
220
- )
221
- if not 0 <= target_coverage <= 100:
222
- raise ValueError("target_coverage must be between 0 and 100")
223
-
224
- self.target_coverage = target_coverage
225
- self.project_root = Path(project_root).resolve()
226
-
227
- # Initialize tracking
228
- self._total_cost = 0.0
229
- self._total_input_tokens = 0
230
- self._total_output_tokens = 0
231
- self._executor = None
232
- self._project_index = None
233
-
234
- # Initialize ProjectIndex if available
235
- try:
236
- from empathy_os.project_index import ProjectIndex
237
-
238
- self._project_index = ProjectIndex(str(self.project_root))
239
- if not self._project_index.load():
240
- print(" [ProjectIndex] Building index (first run)...")
241
- self._project_index.refresh()
242
- else:
243
- print(" [ProjectIndex] Loaded existing index")
244
- except Exception as e:
245
- print(f" [ProjectIndex] Warning: Could not load index: {e}")
246
- self._project_index = None
247
-
248
- # Define agents
249
- self.agents = [
250
- Agent(
251
- role="Gap Analyzer",
252
- goal="Identify critical gaps in test coverage and prioritize them",
253
- backstory="Expert code analyzer specializing in identifying untested code paths. "
254
- "You understand which functions are most critical to test based on complexity, "
255
- "usage patterns, and risk. You prioritize gaps by impact and provide actionable insights.",
256
- expertise_level="expert",
257
- ),
258
- Agent(
259
- role="Test Generator",
260
- goal="Generate comprehensive, high-quality test cases for coverage gaps",
261
- backstory="Senior test engineer who writes clean, maintainable, effective tests. "
262
- "You follow testing best practices, use appropriate assertions, cover edge cases, "
263
- "and write tests that are both thorough and readable.",
264
- expertise_level="expert",
265
- ),
266
- Agent(
267
- role="Test Validator",
268
- goal="Validate generated tests and measure coverage improvement",
269
- backstory="QA specialist focused on test quality and coverage metrics. "
270
- "You verify that tests are correct, run successfully, and actually improve coverage. "
271
- "You identify issues with generated tests and recommend fixes.",
272
- expertise_level="expert",
273
- ),
274
- ]
275
-
276
- def _initialize_executor(self):
277
- """Initialize LLM executor for agent calls."""
278
- if self._executor is not None:
279
- return
280
-
281
- try:
282
- from empathy_os.models.empathy_executor import EmpathyLLMExecutor
283
-
284
- self._executor = EmpathyLLMExecutor(provider="anthropic")
285
- except Exception as e:
286
- print(f" [LLM] Warning: Could not initialize executor: {e}")
287
- print(" [LLM] Workflow will use mock responses")
288
- self._executor = None
289
-
290
- def define_tasks(self) -> list[Task]:
291
- """Define tasks for each agent."""
292
- return [
293
- Task(
294
- description="Analyze the codebase and identify critical test coverage gaps",
295
- expected_output="""JSON object with:
296
- {
297
- "gaps": [
298
- {
299
- "file_path": "path/to/file.py",
300
- "function": "function_name",
301
- "line_start": 10,
302
- "line_end": 50,
303
- "priority": 0.9,
304
- "reason": "High complexity function with no tests"
305
- }
306
- ],
307
- "current_coverage": 65.0,
308
- "summary": "Found 5 critical gaps in high-impact files"
309
- }""",
310
- context_keys=[
311
- "project_root",
312
- "target_coverage",
313
- "project_stats",
314
- "coverage_data",
315
- "files_to_analyze",
316
- "high_impact_files",
317
- ],
318
- ),
319
- Task(
320
- description="Generate comprehensive test cases for the identified coverage gaps",
321
- expected_output="""JSON object with properly escaped strings:
322
- {
323
- "tests": [
324
- {
325
- "test_name": "test_function_name_edge_case",
326
- "test_code": "def test_function_name_edge_case():\\n assert result == \\"expected\\"\\n assert x != \\"bad\\"",
327
- "target_function": "function_name",
328
- "target_file": "path/to/file.py",
329
- "coverage_impact": 5.2
330
- }
331
- ],
332
- "total_tests": 5,
333
- "estimated_coverage_gain": 12.5
334
- }
335
-
336
- CRITICAL FORMATTING RULES:
337
- 1. ALWAYS escape quotes in test_code: Use \\" not "
338
- 2. Use \\n for newlines in test_code
339
- 3. Example CORRECT: "test_code": "def test():\\n assert x == \\"value\\""
340
- 4. Example WRONG: "test_code": "def test(): assert x == "value""
341
- 5. Keep test_code concise - max 5 lines per test""",
342
- context_keys=["gaps", "project_root", "existing_tests"],
343
- ),
344
- Task(
345
- description="Validate the generated tests and measure actual coverage improvement",
346
- expected_output="""JSON object with:
347
- {
348
- "tests_passing": 4,
349
- "tests_failing": 1,
350
- "final_coverage": 77.5,
351
- "coverage_improvement": 12.5,
352
- "issues": ["test_foo failed: assertion error"],
353
- "recommendations": ["Add fixture for database setup"]
354
- }""",
355
- context_keys=["generated_tests", "target_coverage"],
356
- ),
357
- ]
358
-
359
- def _get_file_contents_for_analysis(self, files: list) -> list[dict]:
360
- """Read actual file contents for analysis.
361
-
362
- Args:
363
- files: List of FileRecord objects
364
-
365
- Returns:
366
- List of dicts with path, code, and metadata
367
- """
368
- result = []
369
- for file in files:
370
- try:
371
- file_path = self.project_root / file.path
372
- if not file_path.exists() or not file_path.suffix == ".py":
373
- continue
374
-
375
- code = file_path.read_text(encoding="utf-8")
376
-
377
- # Limit code size to avoid token bloat (max ~5000 chars per file)
378
- if len(code) > 5000:
379
- code = code[:5000] + f"\n... (truncated, {len(code) - 5000} more chars)"
380
-
381
- result.append(
382
- {
383
- "path": str(file.path),
384
- "complexity": file.complexity_score,
385
- "lines": file.lines_of_code,
386
- "has_test": file.tests_exist,
387
- "coverage": file.coverage_percent,
388
- "code": code,
389
- }
390
- )
391
- except Exception:
392
- # Skip files that can't be read
393
- continue
394
-
395
- return result
396
-
397
- def _get_project_context(self) -> dict:
398
- """Get project context from ProjectIndex."""
399
- if self._project_index is None:
400
- return {
401
- "project_root": str(self.project_root),
402
- "target_coverage": self.target_coverage,
403
- }
404
-
405
- try:
406
- summary = self._project_index.get_summary()
407
-
408
- # Get files needing tests for gap analysis
409
- files_needing_tests = self._project_index.get_files_needing_tests()
410
-
411
- # Get high impact files for prioritization
412
- high_impact_files = self._project_index.get_high_impact_files()
413
-
414
- return {
415
- "project_root": str(self.project_root),
416
- "target_coverage": self.target_coverage,
417
- "project_stats": {
418
- "total_files": summary.total_files,
419
- "source_files": summary.source_files,
420
- "test_files": summary.test_files,
421
- "total_loc": summary.total_lines_of_code,
422
- "avg_complexity": summary.avg_complexity,
423
- "test_coverage_avg": summary.test_coverage_avg,
424
- },
425
- "coverage_data": {
426
- "current_coverage": summary.test_coverage_avg,
427
- "files_without_tests": summary.files_without_tests,
428
- "files_needing_tests": len(files_needing_tests),
429
- },
430
- "files_to_analyze": self._get_file_contents_for_analysis(
431
- files_needing_tests[:5]
432
- ), # Top 5 files with code
433
- "high_impact_files": [
434
- {
435
- "path": str(file.path),
436
- "impact_score": file.impact_score,
437
- "complexity": file.complexity_score,
438
- "lines": file.lines_of_code,
439
- }
440
- for file in high_impact_files[:5] # Top 5 high-impact files
441
- ],
442
- }
443
- except Exception as e:
444
- print(f" [ProjectIndex] Could not load project data: {e}")
445
- return {
446
- "project_root": str(self.project_root),
447
- "target_coverage": self.target_coverage,
448
- }
449
-
450
- async def _call_llm(
451
- self,
452
- agent: Agent,
453
- task: Task,
454
- context: dict,
455
- ) -> tuple[str, int, int, float]:
456
- """Call the LLM with agent/task configuration.
457
-
458
- Returns: (response_text, input_tokens, output_tokens, cost)
459
- """
460
- system_prompt = agent.get_system_prompt()
461
- user_prompt = task.get_user_prompt(context)
462
-
463
- if self._executor is None:
464
- # Fallback: return mock response
465
- return await self._mock_llm_call(agent, task)
466
-
467
- try:
468
- # Create execution context
469
- exec_context = ExecutionContext(
470
- task_type="test_generation",
471
- workflow_name="test-coverage-boost",
472
- step_name=agent.role,
473
- )
474
-
475
- # Execute with timeout using correct LLMExecutor API
476
- result = await asyncio.wait_for(
477
- self._executor.run(
478
- task_type="test_generation",
479
- prompt=user_prompt,
480
- system=system_prompt,
481
- context=exec_context,
482
- ),
483
- timeout=120.0,
484
- )
485
-
486
- response = result.content
487
- input_tokens = result.input_tokens
488
- output_tokens = result.output_tokens
489
- cost = result.cost
490
-
491
- # Track totals
492
- self._total_cost += cost
493
- self._total_input_tokens += input_tokens
494
- self._total_output_tokens += output_tokens
495
-
496
- return (response, input_tokens, output_tokens, cost)
497
-
498
- except asyncio.TimeoutError:
499
- print(f" [LLM] Timeout calling {agent.role}")
500
- return await self._mock_llm_call(agent, task, reason="Timeout")
501
- except Exception as e:
502
- print(f" [LLM] Error calling {agent.role}: {e}")
503
- return await self._mock_llm_call(agent, task, reason=str(e))
504
-
505
- async def _mock_llm_call(
506
- self,
507
- agent: Agent,
508
- task: Task,
509
- reason: str = "Executor not available",
510
- ) -> tuple[str, int, int, float]:
511
- """Return mock response when LLM is unavailable."""
512
- print(f" [LLM] Using mock response for {agent.role}: {reason}")
513
-
514
- # Simple mock responses based on agent role
515
- if "Gap Analyzer" in agent.role:
516
- response = json.dumps(
517
- {
518
- "gaps": [
519
- {
520
- "file_path": "src/core.py",
521
- "function": "process_data",
522
- "line_start": 10,
523
- "line_end": 50,
524
- "priority": 0.9,
525
- "reason": "High complexity function with no tests",
526
- }
527
- ],
528
- "current_coverage": 65.0,
529
- "summary": "Mock response - no real gaps analyzed",
530
- }
531
- )
532
- elif "Test Generator" in agent.role:
533
- response = json.dumps({"tests": [], "total_tests": 0, "estimated_coverage_gain": 0.0})
534
- else: # Validator
535
- response = json.dumps(
536
- {
537
- "tests_passing": 0,
538
- "tests_failing": 0,
539
- "final_coverage": 65.0,
540
- "coverage_improvement": 0.0,
541
- "issues": ["Mock response - no real validation performed"],
542
- "recommendations": [],
543
- }
544
- )
545
-
546
- return (response, 0, 0, 0.0)
547
-
548
- async def execute(
549
- self,
550
- project_root: str | None = None,
551
- context: dict | None = None,
552
- **kwargs, # Accept extra parameters from CLI
553
- ) -> TestCoverageBoostCrewResult:
554
- """Execute the test coverage boost crew.
555
-
556
- Args:
557
- project_root: Path to project root (overrides init value)
558
- context: Additional context for agents
559
- **kwargs: Additional arguments (e.g., target_coverage passed by CLI)
560
-
561
- Returns:
562
- TestCoverageBoostCrewResult with detailed outcomes
563
- """
564
- if project_root:
565
- self.project_root = Path(project_root).resolve()
566
-
567
- # Merge kwargs into context for CLI compatibility
568
- context = context or {}
569
- context.update(kwargs)
570
-
571
- started_at = datetime.now()
572
-
573
- print("\n" + "=" * 70)
574
- print(" TEST COVERAGE BOOST CREW")
575
- print("=" * 70)
576
- print(f"\n Project Root: {self.project_root}")
577
- print(f" Target Coverage: {self.target_coverage}%")
578
- print(f" Agents: {len(self.agents)} (sequential execution)")
579
- print("")
580
-
581
- # Initialize executor
582
- self._initialize_executor()
583
-
584
- # Get project context
585
- agent_context = self._get_project_context()
586
- agent_context.update(context)
587
-
588
- # Define tasks
589
- tasks = self.define_tasks()
590
-
591
- # Execute agents sequentially, passing results forward
592
- print(" 🚀 Executing agents sequentially...\n")
593
-
594
- # Agent 1: Gap Analyzer
595
- print(f" • {self.agents[0].role}")
596
- gap_response, _, _, _ = await self._call_llm(self.agents[0], tasks[0], agent_context)
597
- gap_data = self._parse_gap_analysis(gap_response)
598
- agent_context["gaps"] = gap_data.get("gaps", [])
599
- agent_context["current_coverage"] = gap_data.get("current_coverage", 0.0)
600
-
601
- # Agent 2: Test Generator
602
- print(f" • {self.agents[1].role}")
603
- gen_response, _, _, _ = await self._call_llm(self.agents[1], tasks[1], agent_context)
604
- test_data = self._parse_test_generation(gen_response)
605
- agent_context["generated_tests"] = test_data.get("tests", [])
606
-
607
- # Agent 3: Test Validator
608
- print(f" • {self.agents[2].role}")
609
- val_response, _, _, _ = await self._call_llm(self.agents[2], tasks[2], agent_context)
610
- validation_data = self._parse_validation(val_response)
611
-
612
- print("\n ✓ All agents completed\n")
613
-
614
- # Build result
615
- current_coverage = gap_data.get("current_coverage", 0.0)
616
- final_coverage = validation_data.get("final_coverage", current_coverage)
617
- coverage_improvement = final_coverage - current_coverage
618
-
619
- # Parse gaps into CoverageGap objects
620
- gaps_analyzed = []
621
- for gap in gap_data.get("gaps", [])[:5]: # Top 5 gaps
622
- gaps_analyzed.append(
623
- CoverageGap(
624
- file_path=gap.get("file_path", "unknown"),
625
- function_name=gap.get("function", "unknown"),
626
- line_start=gap.get("line_start", 0),
627
- line_end=gap.get("line_end", 0),
628
- priority=gap.get("priority", 0.5),
629
- reason=gap.get("reason", "No reason provided"),
630
- )
631
- )
632
-
633
- # Parse generated tests into GeneratedTest objects
634
- generated_tests = []
635
- for test in test_data.get("tests", []):
636
- generated_tests.append(
637
- GeneratedTest(
638
- test_name=test.get("test_name", "test_unknown"),
639
- test_code=test.get("test_code", ""),
640
- target_function=test.get("target_function", "unknown"),
641
- target_file=test.get("target_file", "unknown"),
642
- coverage_impact=test.get("coverage_impact", 0.0),
643
- )
644
- )
645
-
646
- # Calculate duration
647
- duration_ms = int((datetime.now() - started_at).total_seconds() * 1000)
648
-
649
- result = TestCoverageBoostCrewResult(
650
- success=True,
651
- current_coverage=current_coverage,
652
- target_coverage=self.target_coverage,
653
- final_coverage=final_coverage,
654
- coverage_improvement=coverage_improvement,
655
- gaps_found=len(gap_data.get("gaps", [])),
656
- tests_generated=test_data.get("total_tests", 0),
657
- tests_passing=validation_data.get("tests_passing", 0),
658
- gaps_analyzed=gaps_analyzed,
659
- generated_tests=generated_tests,
660
- agents_executed=len(self.agents),
661
- cost=self._total_cost,
662
- duration_ms=duration_ms,
663
- )
664
-
665
- # Print formatted report
666
- print(self._format_report(result))
667
-
668
- return result
669
-
670
- def _parse_gap_analysis(self, response: str) -> dict:
671
- """Parse gap analysis response."""
672
- parsed = parse_xml_response(response)
673
- answer = parsed["answer"]
674
-
675
- # Clean up answer - strip ALL XML tags and code blocks
676
- answer = re.sub(r"</?answer>", "", answer) # Remove all <answer> and </answer> tags
677
- answer = re.sub(r"```json\s*", "", answer) # Remove ```json
678
- answer = re.sub(r"```\s*", "", answer) # Remove closing ```
679
- answer = answer.strip()
680
-
681
- try:
682
- data = json.loads(answer)
683
- return data
684
- except json.JSONDecodeError:
685
- # Try regex extraction
686
- gaps = []
687
- current_coverage = 0.0
688
-
689
- # Extract coverage
690
- cov_match = re.search(r'"current_coverage"\s*:\s*(\d+\.?\d*)', answer)
691
- if cov_match:
692
- current_coverage = float(cov_match.group(1))
693
-
694
- return {
695
- "gaps": gaps,
696
- "current_coverage": current_coverage,
697
- "summary": "Could not parse gap analysis",
698
- }
699
-
700
- def _parse_test_generation(self, response: str) -> dict:
701
- """Parse test generation response."""
702
- parsed = parse_xml_response(response)
703
- answer = parsed["answer"]
704
-
705
- # Clean up answer - strip ALL XML tags and code blocks
706
- answer = re.sub(r"</?answer>", "", answer) # Remove all <answer> and </answer> tags
707
- answer = re.sub(r"```json\s*", "", answer) # Remove ```json
708
- answer = re.sub(r"```\s*", "", answer) # Remove closing ```
709
- answer = answer.strip()
710
-
711
- try:
712
- data = json.loads(answer)
713
- return data
714
- except json.JSONDecodeError:
715
- # JSON parsing failed - attempt regex extraction
716
- tests = []
717
-
718
- # Pattern to extract test objects (handles malformed JSON)
719
- # More lenient pattern - looks for key fields in any order
720
- test_blocks = re.finditer(
721
- r'\{[^}]*"test_name"\s*:\s*"([^"]+)"[^}]*\}', answer, re.DOTALL
722
- )
723
-
724
- for match in test_blocks:
725
- block_text = match.group(0)
726
-
727
- # Extract test_name
728
- test_name_match = re.search(r'"test_name"\s*:\s*"([^"]+)"', block_text)
729
- test_name = test_name_match.group(1) if test_name_match else "test_unknown"
730
-
731
- # Extract test_code (handles escaped quotes)
732
- test_code_match = re.search(
733
- r'"test_code"\s*:\s*"((?:[^"\\]|\\.)*?)"', block_text, re.DOTALL
734
- )
735
- test_code = test_code_match.group(1) if test_code_match else ""
736
-
737
- # Extract target_function
738
- func_match = re.search(r'"target_function"\s*:\s*"([^"]*)"', block_text)
739
- target_function = func_match.group(1) if func_match else "unknown"
740
-
741
- # Extract target_file
742
- file_match = re.search(r'"target_file"\s*:\s*"([^"]*)"', block_text)
743
- target_file = file_match.group(1) if file_match else "unknown"
744
-
745
- # Unescape the test code
746
- test_code = test_code.replace("\\n", "\n").replace('\\"', '"').replace("\\\\", "\\")
747
-
748
- tests.append(
749
- {
750
- "test_name": test_name,
751
- "test_code": test_code,
752
- "target_function": target_function,
753
- "target_file": target_file,
754
- "coverage_impact": 0.0,
755
- }
756
- )
757
-
758
- # Try to extract total_tests
759
- total_tests = len(tests)
760
- total_match = re.search(r'"total_tests"\s*:\s*(\d+)', answer)
761
- if total_match:
762
- total_tests = max(total_tests, int(total_match.group(1)))
763
-
764
- # Extract estimated coverage gain
765
- coverage_gain = 0.0
766
- gain_match = re.search(r'"estimated_coverage_gain"\s*:\s*(\d+\.?\d*)', answer)
767
- if gain_match:
768
- coverage_gain = float(gain_match.group(1))
769
-
770
- return {
771
- "tests": tests,
772
- "total_tests": total_tests,
773
- "estimated_coverage_gain": coverage_gain,
774
- }
775
-
776
- def _parse_validation(self, response: str) -> dict:
777
- """Parse validation response."""
778
- parsed = parse_xml_response(response)
779
- answer = parsed["answer"]
780
-
781
- # Clean up answer - strip ALL XML tags and code blocks
782
- answer = re.sub(r"</?answer>", "", answer) # Remove all <answer> and </answer> tags
783
- answer = re.sub(r"```json\s*", "", answer) # Remove ```json
784
- answer = re.sub(r"```\s*", "", answer) # Remove closing ```
785
- answer = answer.strip()
786
-
787
- try:
788
- data = json.loads(answer)
789
- return data
790
- except json.JSONDecodeError:
791
- return {
792
- "tests_passing": 0,
793
- "tests_failing": 0,
794
- "final_coverage": 0.0,
795
- "coverage_improvement": 0.0,
796
- "issues": ["Could not parse validation results"],
797
- "recommendations": [],
798
- }
799
-
800
- def _format_report(self, result: TestCoverageBoostCrewResult) -> str:
801
- """Format result as human-readable report."""
802
- lines = []
803
-
804
- lines.append("=" * 70)
805
- lines.append("TEST COVERAGE BOOST RESULTS")
806
- lines.append("=" * 70)
807
- lines.append("")
808
- lines.append(f"Current Coverage: {result.current_coverage:.1f}%")
809
- lines.append(f"Target Coverage: {result.target_coverage:.1f}%")
810
- lines.append(f"Final Coverage: {result.final_coverage:.1f}%")
811
- lines.append(f"Improvement: +{result.coverage_improvement:.1f}%")
812
- lines.append("")
813
- lines.append(f"Gaps Found: {result.gaps_found}")
814
- lines.append(f"Tests Generated: {result.tests_generated}")
815
- lines.append(f"Tests Passing: {result.tests_passing}")
816
- lines.append("")
817
- lines.append(f"Cost: ${result.cost:.4f}")
818
- lines.append(f"Duration: {result.duration_ms}ms ({result.duration_ms / 1000:.1f}s)")
819
- lines.append("")
820
-
821
- if result.gaps_analyzed:
822
- lines.append("-" * 70)
823
- lines.append("TOP COVERAGE GAPS")
824
- lines.append("-" * 70)
825
- for i, gap in enumerate(result.gaps_analyzed[:5], 1):
826
- lines.append(
827
- f"{i}. {gap.file_path}::{gap.function_name} (priority: {gap.priority:.2f})"
828
- )
829
- lines.append(f" {gap.reason}")
830
- lines.append("")
831
-
832
- if result.generated_tests:
833
- lines.append("-" * 70)
834
- lines.append("GENERATED TESTS")
835
- lines.append("-" * 70)
836
- for i, test in enumerate(result.generated_tests[:3], 1):
837
- lines.append(f"{i}. {test.test_name}")
838
- lines.append(f" Target: {test.target_file}::{test.target_function}")
839
- lines.append(f" Impact: +{test.coverage_impact:.1f}%")
840
- lines.append("")
841
-
842
- lines.append("=" * 70)
843
- if result.coverage_improvement > 0:
844
- lines.append(f"✅ Coverage improved by {result.coverage_improvement:.1f}%")
845
- else:
846
- lines.append("⚠️ No coverage improvement achieved")
847
- lines.append("=" * 70)
848
-
849
- return "\n".join(lines)