empathy-framework 4.6.6__py3-none-any.whl → 4.7.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 (247) hide show
  1. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/METADATA +7 -6
  2. empathy_framework-4.7.0.dist-info/RECORD +354 -0
  3. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/top_level.txt +0 -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.py +173 -0
  130. empathy_os/workflows/__init__.py +212 -120
  131. empathy_os/workflows/batch_processing.py +8 -24
  132. empathy_os/workflows/bug_predict.py +1 -1
  133. empathy_os/workflows/code_review.py +20 -5
  134. empathy_os/workflows/code_review_pipeline.py +13 -8
  135. empathy_os/workflows/keyboard_shortcuts/workflow.py +6 -2
  136. empathy_os/workflows/manage_documentation.py +1 -0
  137. empathy_os/workflows/orchestrated_health_check.py +6 -11
  138. empathy_os/workflows/orchestrated_release_prep.py +3 -3
  139. empathy_os/workflows/pr_review.py +18 -10
  140. empathy_os/workflows/progressive/__init__.py +2 -12
  141. empathy_os/workflows/progressive/cli.py +14 -37
  142. empathy_os/workflows/progressive/core.py +12 -12
  143. empathy_os/workflows/progressive/orchestrator.py +166 -144
  144. empathy_os/workflows/progressive/reports.py +22 -31
  145. empathy_os/workflows/progressive/telemetry.py +8 -14
  146. empathy_os/workflows/progressive/test_gen.py +29 -48
  147. empathy_os/workflows/progressive/workflow.py +31 -70
  148. empathy_os/workflows/release_prep.py +21 -6
  149. empathy_os/workflows/release_prep_crew.py +1 -0
  150. empathy_os/workflows/secure_release.py +13 -6
  151. empathy_os/workflows/security_audit.py +8 -3
  152. empathy_os/workflows/test_coverage_boost_crew.py +3 -2
  153. empathy_os/workflows/test_maintenance_crew.py +1 -0
  154. empathy_os/workflows/test_runner.py +16 -12
  155. empathy_software_plugin/SOFTWARE_PLUGIN_README.md +25 -703
  156. empathy_software_plugin/cli.py +0 -122
  157. coach_wizards/__init__.py +0 -45
  158. coach_wizards/accessibility_wizard.py +0 -91
  159. coach_wizards/api_wizard.py +0 -91
  160. coach_wizards/base_wizard.py +0 -209
  161. coach_wizards/cicd_wizard.py +0 -91
  162. coach_wizards/code_reviewer_README.md +0 -60
  163. coach_wizards/code_reviewer_wizard.py +0 -180
  164. coach_wizards/compliance_wizard.py +0 -91
  165. coach_wizards/database_wizard.py +0 -91
  166. coach_wizards/debugging_wizard.py +0 -91
  167. coach_wizards/documentation_wizard.py +0 -91
  168. coach_wizards/generate_wizards.py +0 -347
  169. coach_wizards/localization_wizard.py +0 -173
  170. coach_wizards/migration_wizard.py +0 -91
  171. coach_wizards/monitoring_wizard.py +0 -91
  172. coach_wizards/observability_wizard.py +0 -91
  173. coach_wizards/performance_wizard.py +0 -91
  174. coach_wizards/prompt_engineering_wizard.py +0 -661
  175. coach_wizards/refactoring_wizard.py +0 -91
  176. coach_wizards/scaling_wizard.py +0 -90
  177. coach_wizards/security_wizard.py +0 -92
  178. coach_wizards/testing_wizard.py +0 -91
  179. empathy_framework-4.6.6.dist-info/RECORD +0 -410
  180. empathy_llm_toolkit/wizards/__init__.py +0 -43
  181. empathy_llm_toolkit/wizards/base_wizard.py +0 -364
  182. empathy_llm_toolkit/wizards/customer_support_wizard.py +0 -190
  183. empathy_llm_toolkit/wizards/healthcare_wizard.py +0 -378
  184. empathy_llm_toolkit/wizards/patient_assessment_README.md +0 -64
  185. empathy_llm_toolkit/wizards/patient_assessment_wizard.py +0 -193
  186. empathy_llm_toolkit/wizards/technology_wizard.py +0 -209
  187. empathy_os/wizard_factory_cli.py +0 -170
  188. empathy_software_plugin/wizards/__init__.py +0 -42
  189. empathy_software_plugin/wizards/advanced_debugging_wizard.py +0 -395
  190. empathy_software_plugin/wizards/agent_orchestration_wizard.py +0 -511
  191. empathy_software_plugin/wizards/ai_collaboration_wizard.py +0 -503
  192. empathy_software_plugin/wizards/ai_context_wizard.py +0 -441
  193. empathy_software_plugin/wizards/ai_documentation_wizard.py +0 -503
  194. empathy_software_plugin/wizards/base_wizard.py +0 -288
  195. empathy_software_plugin/wizards/book_chapter_wizard.py +0 -519
  196. empathy_software_plugin/wizards/code_review_wizard.py +0 -604
  197. empathy_software_plugin/wizards/debugging/__init__.py +0 -50
  198. empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +0 -414
  199. empathy_software_plugin/wizards/debugging/config_loaders.py +0 -446
  200. empathy_software_plugin/wizards/debugging/fix_applier.py +0 -469
  201. empathy_software_plugin/wizards/debugging/language_patterns.py +0 -385
  202. empathy_software_plugin/wizards/debugging/linter_parsers.py +0 -470
  203. empathy_software_plugin/wizards/debugging/verification.py +0 -369
  204. empathy_software_plugin/wizards/enhanced_testing_wizard.py +0 -537
  205. empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +0 -816
  206. empathy_software_plugin/wizards/multi_model_wizard.py +0 -501
  207. empathy_software_plugin/wizards/pattern_extraction_wizard.py +0 -422
  208. empathy_software_plugin/wizards/pattern_retriever_wizard.py +0 -400
  209. empathy_software_plugin/wizards/performance/__init__.py +0 -9
  210. empathy_software_plugin/wizards/performance/bottleneck_detector.py +0 -221
  211. empathy_software_plugin/wizards/performance/profiler_parsers.py +0 -278
  212. empathy_software_plugin/wizards/performance/trajectory_analyzer.py +0 -429
  213. empathy_software_plugin/wizards/performance_profiling_wizard.py +0 -305
  214. empathy_software_plugin/wizards/prompt_engineering_wizard.py +0 -425
  215. empathy_software_plugin/wizards/rag_pattern_wizard.py +0 -461
  216. empathy_software_plugin/wizards/security/__init__.py +0 -32
  217. empathy_software_plugin/wizards/security/exploit_analyzer.py +0 -290
  218. empathy_software_plugin/wizards/security/owasp_patterns.py +0 -241
  219. empathy_software_plugin/wizards/security/vulnerability_scanner.py +0 -604
  220. empathy_software_plugin/wizards/security_analysis_wizard.py +0 -322
  221. empathy_software_plugin/wizards/security_learning_wizard.py +0 -740
  222. empathy_software_plugin/wizards/tech_debt_wizard.py +0 -726
  223. empathy_software_plugin/wizards/testing/__init__.py +0 -27
  224. empathy_software_plugin/wizards/testing/coverage_analyzer.py +0 -459
  225. empathy_software_plugin/wizards/testing/quality_analyzer.py +0 -525
  226. empathy_software_plugin/wizards/testing/test_suggester.py +0 -533
  227. empathy_software_plugin/wizards/testing_wizard.py +0 -274
  228. wizards/__init__.py +0 -82
  229. wizards/admission_assessment_wizard.py +0 -644
  230. wizards/care_plan.py +0 -321
  231. wizards/clinical_assessment.py +0 -769
  232. wizards/discharge_planning.py +0 -77
  233. wizards/discharge_summary_wizard.py +0 -468
  234. wizards/dosage_calculation.py +0 -497
  235. wizards/incident_report_wizard.py +0 -454
  236. wizards/medication_reconciliation.py +0 -85
  237. wizards/nursing_assessment.py +0 -171
  238. wizards/patient_education.py +0 -654
  239. wizards/quality_improvement.py +0 -705
  240. wizards/sbar_report.py +0 -324
  241. wizards/sbar_wizard.py +0 -608
  242. wizards/shift_handoff_wizard.py +0 -535
  243. wizards/soap_note_wizard.py +0 -679
  244. wizards/treatment_plan.py +0 -15
  245. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/WHEEL +0 -0
  246. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/entry_points.txt +0 -0
  247. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -149,7 +149,7 @@ class TFIDFEmbeddingProvider(EmbeddingProvider):
149
149
  """Tokenize text into words."""
150
150
  # Simple tokenization: lowercase, split on non-alphanumeric
151
151
  text = text.lower()
152
- tokens = re.findall(r'\b[a-z][a-z0-9_]*\b', text)
152
+ tokens = re.findall(r"\b[a-z][a-z0-9_]*\b", text)
153
153
  return tokens
154
154
 
155
155
  def _compute_tf(self, tokens: list[str]) -> dict[str, float]:
@@ -255,6 +255,7 @@ class AnthropicEmbeddingProvider(EmbeddingProvider):
255
255
  if self._client is None and self.api_key:
256
256
  try:
257
257
  import anthropic
258
+
258
259
  self._client = anthropic.Anthropic(api_key=self.api_key)
259
260
  except ImportError:
260
261
  logger.warning("anthropic package not installed")
@@ -268,13 +269,13 @@ class AnthropicEmbeddingProvider(EmbeddingProvider):
268
269
  fallback = TFIDFEmbeddingProvider(dimension=self._dimension)
269
270
  return fallback.embed(text)
270
271
 
271
- aspects = self.ASPECTS[:self._dimension]
272
+ aspects = self.ASPECTS[: self._dimension]
272
273
  prompt = f"""Rate how relevant this goal is to each aspect on a scale of 0.0 to 1.0.
273
274
 
274
275
  Goal: "{text}"
275
276
 
276
277
  Aspects to rate:
277
- {chr(10).join(f'{i+1}. {aspect}' for i, aspect in enumerate(aspects))}
278
+ {chr(10).join(f"{i + 1}. {aspect}" for i, aspect in enumerate(aspects))}
278
279
 
279
280
  Respond with ONLY a JSON array of numbers, one per aspect, in order.
280
281
  Example: [0.8, 0.2, 0.5, ...]"""
@@ -290,7 +291,7 @@ Example: [0.8, 0.2, 0.5, ...]"""
290
291
  # Parse JSON array
291
292
  scores = json.loads(content.strip())
292
293
  if isinstance(scores, list) and len(scores) >= self._dimension:
293
- return [float(s) for s in scores[:self._dimension]]
294
+ return [float(s) for s in scores[: self._dimension]]
294
295
 
295
296
  except Exception as e:
296
297
  logger.warning(f"Anthropic embedding failed: {e}")
@@ -331,6 +332,7 @@ class SentenceTransformerProvider(EmbeddingProvider):
331
332
  if self._model is None:
332
333
  try:
333
334
  from sentence_transformers import SentenceTransformer
335
+
334
336
  self._model = SentenceTransformer(self.model_name)
335
337
  self._dimension = self._model.get_sentence_embedding_dimension()
336
338
  except ImportError:
@@ -677,15 +679,17 @@ class SemanticGoalMatcher:
677
679
  formatted = []
678
680
  for result in results:
679
681
  if result.goal.success_score >= min_success_score:
680
- formatted.append({
681
- "goal_id": result.goal.goal_id,
682
- "goal_text": result.goal.goal_text,
683
- "similarity": round(result.similarity, 3),
684
- "workflow_id": result.goal.workflow_id,
685
- "domains": result.goal.domains,
686
- "success_score": result.goal.success_score,
687
- "metadata": result.goal.metadata,
688
- })
682
+ formatted.append(
683
+ {
684
+ "goal_id": result.goal.goal_id,
685
+ "goal_text": result.goal.goal_text,
686
+ "similarity": round(result.similarity, 3),
687
+ "workflow_id": result.goal.workflow_id,
688
+ "domains": result.goal.domains,
689
+ "success_score": result.goal.success_score,
690
+ "metadata": result.goal.metadata,
691
+ }
692
+ )
689
693
 
690
694
  if len(formatted) >= top_k:
691
695
  break
@@ -144,9 +144,32 @@ def extract_keywords(goal: str) -> list[str]:
144
144
  """Extract important keywords from goal."""
145
145
  # Remove common words
146
146
  stop_words = {
147
- "i", "want", "to", "the", "a", "an", "my", "our", "for", "with",
148
- "that", "this", "is", "are", "be", "will", "would", "could",
149
- "should", "can", "help", "me", "us", "please", "need", "like",
147
+ "i",
148
+ "want",
149
+ "to",
150
+ "the",
151
+ "a",
152
+ "an",
153
+ "my",
154
+ "our",
155
+ "for",
156
+ "with",
157
+ "that",
158
+ "this",
159
+ "is",
160
+ "are",
161
+ "be",
162
+ "will",
163
+ "would",
164
+ "could",
165
+ "should",
166
+ "can",
167
+ "help",
168
+ "me",
169
+ "us",
170
+ "please",
171
+ "need",
172
+ "like",
150
173
  }
151
174
 
152
175
  # Extract words
@@ -162,7 +185,10 @@ def identify_ambiguities(goal: str, domain: str) -> list[str]:
162
185
  ambiguities = []
163
186
 
164
187
  # Check for missing specifics
165
- if not any(lang in goal.lower() for lang in ["python", "javascript", "typescript", "java", "go", "rust"]):
188
+ if not any(
189
+ lang in goal.lower()
190
+ for lang in ["python", "javascript", "typescript", "java", "go", "rust"]
191
+ ):
166
192
  ambiguities.append("Programming language not specified")
167
193
 
168
194
  # Check for vague scope
@@ -223,50 +249,78 @@ def generate_initial_questions(
223
249
 
224
250
  # Domain-specific questions
225
251
  if goal_analysis.domain == "code_review":
226
- fields.append(FormField(
227
- id="review_scope",
228
- field_type=FieldType.SINGLE_SELECT,
229
- label="What scope of review do you need?",
230
- options=[
231
- FieldOption("pr", "Pull Request/Diff", description="Review specific changes", recommended=True),
232
- FieldOption("file", "Single File", description="Deep review of one file"),
233
- FieldOption("directory", "Directory/Module", description="Review entire module"),
234
- FieldOption("project", "Full Project", description="Comprehensive codebase review"),
235
- ],
236
- validation=FieldValidation(required=True),
237
- category="scope",
238
- ))
252
+ fields.append(
253
+ FormField(
254
+ id="review_scope",
255
+ field_type=FieldType.SINGLE_SELECT,
256
+ label="What scope of review do you need?",
257
+ options=[
258
+ FieldOption(
259
+ "pr",
260
+ "Pull Request/Diff",
261
+ description="Review specific changes",
262
+ recommended=True,
263
+ ),
264
+ FieldOption("file", "Single File", description="Deep review of one file"),
265
+ FieldOption(
266
+ "directory", "Directory/Module", description="Review entire module"
267
+ ),
268
+ FieldOption(
269
+ "project", "Full Project", description="Comprehensive codebase review"
270
+ ),
271
+ ],
272
+ validation=FieldValidation(required=True),
273
+ category="scope",
274
+ )
275
+ )
239
276
 
240
277
  if goal_analysis.domain == "security":
241
- fields.append(FormField(
242
- id="security_focus",
243
- field_type=FieldType.MULTI_SELECT,
244
- label="What security aspects are most important?",
245
- options=[
246
- FieldOption("owasp", "OWASP Top 10", description="Common web vulnerabilities"),
247
- FieldOption("injection", "Injection Attacks", description="SQL, command, XSS"),
248
- FieldOption("auth", "Authentication/Authorization", description="Access control issues"),
249
- FieldOption("crypto", "Cryptography", description="Encryption, hashing, secrets"),
250
- FieldOption("deps", "Dependencies", description="Vulnerable dependencies"),
251
- ],
252
- validation=FieldValidation(required=True),
253
- category="security",
254
- ))
278
+ fields.append(
279
+ FormField(
280
+ id="security_focus",
281
+ field_type=FieldType.MULTI_SELECT,
282
+ label="What security aspects are most important?",
283
+ options=[
284
+ FieldOption("owasp", "OWASP Top 10", description="Common web vulnerabilities"),
285
+ FieldOption("injection", "Injection Attacks", description="SQL, command, XSS"),
286
+ FieldOption(
287
+ "auth", "Authentication/Authorization", description="Access control issues"
288
+ ),
289
+ FieldOption(
290
+ "crypto", "Cryptography", description="Encryption, hashing, secrets"
291
+ ),
292
+ FieldOption("deps", "Dependencies", description="Vulnerable dependencies"),
293
+ ],
294
+ validation=FieldValidation(required=True),
295
+ category="security",
296
+ )
297
+ )
255
298
 
256
299
  if goal_analysis.domain == "testing":
257
- fields.append(FormField(
258
- id="test_type",
259
- field_type=FieldType.MULTI_SELECT,
260
- label="What types of tests do you need?",
261
- options=[
262
- FieldOption("unit", "Unit Tests", description="Test individual functions", recommended=True),
263
- FieldOption("integration", "Integration Tests", description="Test component interactions"),
264
- FieldOption("e2e", "End-to-End Tests", description="Test full user flows"),
265
- FieldOption("edge", "Edge Cases", description="Test boundary conditions"),
266
- ],
267
- validation=FieldValidation(required=True),
268
- category="testing",
269
- ))
300
+ fields.append(
301
+ FormField(
302
+ id="test_type",
303
+ field_type=FieldType.MULTI_SELECT,
304
+ label="What types of tests do you need?",
305
+ options=[
306
+ FieldOption(
307
+ "unit",
308
+ "Unit Tests",
309
+ description="Test individual functions",
310
+ recommended=True,
311
+ ),
312
+ FieldOption(
313
+ "integration",
314
+ "Integration Tests",
315
+ description="Test component interactions",
316
+ ),
317
+ FieldOption("e2e", "End-to-End Tests", description="Test full user flows"),
318
+ FieldOption("edge", "Edge Cases", description="Test boundary conditions"),
319
+ ],
320
+ validation=FieldValidation(required=True),
321
+ category="testing",
322
+ )
323
+ )
270
324
 
271
325
  # Automation level (always relevant)
272
326
  fields.append(create_automation_level_field())
@@ -280,7 +334,7 @@ def generate_initial_questions(
280
334
  return Form(
281
335
  id=f"round_{session.current_round + 1}",
282
336
  title="Help Us Understand Your Needs",
283
- description=f"Based on your goal: \"{goal_analysis.raw_goal[:100]}...\"",
337
+ description=f'Based on your goal: "{goal_analysis.raw_goal[:100]}..."',
284
338
  fields=fields,
285
339
  round_number=session.current_round + 1,
286
340
  progress=0.3,
@@ -305,14 +359,16 @@ def generate_followup_questions(
305
359
 
306
360
  # If no must-haves, ask for priorities
307
361
  if not reqs.must_have:
308
- fields.append(FormField(
309
- id="priorities",
310
- field_type=FieldType.TEXT_AREA,
311
- label="What are your top 3 priorities for this workflow?",
312
- help_text="Be as specific as possible about what success looks like.",
313
- validation=FieldValidation(required=True, min_length=20),
314
- category="priorities",
315
- ))
362
+ fields.append(
363
+ FormField(
364
+ id="priorities",
365
+ field_type=FieldType.TEXT_AREA,
366
+ label="What are your top 3 priorities for this workflow?",
367
+ help_text="Be as specific as possible about what success looks like.",
368
+ validation=FieldValidation(required=True, min_length=20),
369
+ category="priorities",
370
+ )
371
+ )
316
372
 
317
373
  # If technical constraints missing
318
374
  if not reqs.technical_constraints.get("languages"):
@@ -320,18 +376,28 @@ def generate_followup_questions(
320
376
 
321
377
  # Domain-specific follow-ups
322
378
  if session.goal_analysis and session.goal_analysis.domain == "code_review":
323
- if "review_depth" not in [r.get("id") for r in session.question_rounds[-1]["questions"]] if session.question_rounds else True:
324
- fields.append(FormField(
325
- id="review_depth",
326
- field_type=FieldType.SINGLE_SELECT,
327
- label="How thorough should the review be?",
328
- options=[
329
- FieldOption("quick", "Quick Scan", description="Fast, surface-level review"),
330
- FieldOption("standard", "Standard", description="Balanced depth", recommended=True),
331
- FieldOption("deep", "Deep Dive", description="Thorough, detailed analysis"),
332
- ],
333
- category="depth",
334
- ))
379
+ if (
380
+ "review_depth" not in [r.get("id") for r in session.question_rounds[-1]["questions"]]
381
+ if session.question_rounds
382
+ else True
383
+ ):
384
+ fields.append(
385
+ FormField(
386
+ id="review_depth",
387
+ field_type=FieldType.SINGLE_SELECT,
388
+ label="How thorough should the review be?",
389
+ options=[
390
+ FieldOption(
391
+ "quick", "Quick Scan", description="Fast, surface-level review"
392
+ ),
393
+ FieldOption(
394
+ "standard", "Standard", description="Balanced depth", recommended=True
395
+ ),
396
+ FieldOption("deep", "Deep Dive", description="Thorough, detailed analysis"),
397
+ ],
398
+ category="depth",
399
+ )
400
+ )
335
401
 
336
402
  if not fields:
337
403
  return None
@@ -513,10 +579,7 @@ class SocraticWorkflowBuilder:
513
579
  current_form = self.get_next_questions(session)
514
580
  questions_data = []
515
581
  if current_form:
516
- questions_data = [
517
- {"id": f.id, "label": f.label}
518
- for f in current_form.fields
519
- ]
582
+ questions_data = [{"id": f.id, "label": f.label} for f in current_form.fields]
520
583
 
521
584
  session.add_question_round(questions_data, answers)
522
585
 
@@ -725,5 +788,7 @@ class SocraticWorkflowBuilder:
725
788
  "rounds_completed": session.current_round,
726
789
  "requirements_completeness": session.requirements.completeness_score(),
727
790
  "ready_to_generate": self.is_ready_to_generate(session),
728
- "ambiguities_remaining": len(session.goal_analysis.ambiguities) if session.goal_analysis else 0,
791
+ "ambiguities_remaining": (
792
+ len(session.goal_analysis.ambiguities) if session.goal_analysis else 0
793
+ ),
729
794
  }
@@ -206,29 +206,37 @@ class WorkflowExplainer:
206
206
  sections: list[dict[str, str]] = []
207
207
 
208
208
  # Overview section
209
- sections.append({
210
- "heading": "Overview",
211
- "content": self._explain_overview(blueprint),
212
- })
209
+ sections.append(
210
+ {
211
+ "heading": "Overview",
212
+ "content": self._explain_overview(blueprint),
213
+ }
214
+ )
213
215
 
214
216
  # Agents section
215
- sections.append({
216
- "heading": "Agents Involved",
217
- "content": self._explain_agents(blueprint.agents),
218
- })
217
+ sections.append(
218
+ {
219
+ "heading": "Agents Involved",
220
+ "content": self._explain_agents(blueprint.agents),
221
+ }
222
+ )
219
223
 
220
224
  # Process section
221
- sections.append({
222
- "heading": "How It Works",
223
- "content": self._explain_process(blueprint.stages, blueprint.agents),
224
- })
225
+ sections.append(
226
+ {
227
+ "heading": "How It Works",
228
+ "content": self._explain_process(blueprint.stages, blueprint.agents),
229
+ }
230
+ )
225
231
 
226
232
  # Success criteria section (if provided)
227
233
  if success_criteria:
228
- sections.append({
229
- "heading": "Success Metrics",
230
- "content": self._explain_success_criteria(success_criteria),
231
- })
234
+ sections.append(
235
+ {
236
+ "heading": "Success Metrics",
237
+ "content": self._explain_success_criteria(success_criteria),
238
+ }
239
+ )
232
240
 
233
241
  # Summary
234
242
  summary = self._generate_summary(blueprint)
@@ -256,22 +264,28 @@ class WorkflowExplainer:
256
264
  role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(
257
265
  agent.role, "performs automated tasks"
258
266
  )
259
- sections.append({
260
- "heading": "Role",
261
- "content": f"This agent {role_desc}.",
262
- })
267
+ sections.append(
268
+ {
269
+ "heading": "Role",
270
+ "content": f"This agent {role_desc}.",
271
+ }
272
+ )
263
273
 
264
274
  # Capabilities section
265
- sections.append({
266
- "heading": "Capabilities",
267
- "content": self._explain_tools(agent.tools),
268
- })
275
+ sections.append(
276
+ {
277
+ "heading": "Capabilities",
278
+ "content": self._explain_tools(agent.tools),
279
+ }
280
+ )
269
281
 
270
282
  # How it helps section
271
- sections.append({
272
- "heading": "How It Helps",
273
- "content": self._explain_agent_value(agent),
274
- })
283
+ sections.append(
284
+ {
285
+ "heading": "How It Helps",
286
+ "content": self._explain_agent_value(agent),
287
+ }
288
+ )
275
289
 
276
290
  summary = f"{agent.name} is a {agent.role.value} agent that {agent.goal.lower()}"
277
291
 
@@ -298,7 +312,9 @@ class WorkflowExplainer:
298
312
  f"Target domain: {blueprint.domain}."
299
313
  )
300
314
  else:
301
- generated_at = blueprint.generated_at.strftime('%Y-%m-%d') if blueprint.generated_at else 'N/A'
315
+ generated_at = (
316
+ blueprint.generated_at.strftime("%Y-%m-%d") if blueprint.generated_at else "N/A"
317
+ )
302
318
  return (
303
319
  f"Multi-agent workflow with {len(blueprint.agents)} agents, "
304
320
  f"{len(blueprint.stages)} stages. "
@@ -317,15 +333,15 @@ class WorkflowExplainer:
317
333
  for agent_blueprint in agents:
318
334
  # Access the AgentSpec via .spec
319
335
  spec = agent_blueprint.spec
320
- role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(
321
- spec.role, "works on the task"
322
- )
336
+ role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(spec.role, "works on the task")
323
337
 
324
338
  if self.detail_level == DetailLevel.BRIEF:
325
339
  lines.append(f"• {spec.name}: {role_desc}")
326
340
  else:
327
341
  tool_count = len(spec.tools)
328
- tool_str = f" ({tool_count} tools)" if self.detail_level == DetailLevel.DETAILED else ""
342
+ tool_str = (
343
+ f" ({tool_count} tools)" if self.detail_level == DetailLevel.DETAILED else ""
344
+ )
329
345
  lines.append(f"• **{spec.name}**{tool_str}: {spec.goal}")
330
346
 
331
347
  return "\n".join(lines)
@@ -341,11 +357,7 @@ class WorkflowExplainer:
341
357
  lines = []
342
358
 
343
359
  for i, stage in enumerate(stages, 1):
344
- agent_names = [
345
- agent_lookup[aid].name
346
- for aid in stage.agent_ids
347
- if aid in agent_lookup
348
- ]
360
+ agent_names = [agent_lookup[aid].name for aid in stage.agent_ids if aid in agent_lookup]
349
361
 
350
362
  if self.audience == AudienceLevel.BEGINNER:
351
363
  if stage.parallel:
@@ -358,9 +370,7 @@ class WorkflowExplainer:
358
370
  )
359
371
  else:
360
372
  parallel_str = " (parallel)" if stage.parallel else ""
361
- lines.append(
362
- f"{i}. **{stage.name}**{parallel_str}: {', '.join(agent_names)}"
363
- )
373
+ lines.append(f"{i}. **{stage.name}**{parallel_str}: {', '.join(agent_names)}")
364
374
 
365
375
  if self.detail_level == DetailLevel.DETAILED and stage.depends_on:
366
376
  lines.append(f" Depends on: {', '.join(stage.depends_on)}")
@@ -384,7 +394,7 @@ class WorkflowExplainer:
384
394
 
385
395
  lines = ["This agent can:"]
386
396
  for tool in tools:
387
- tool_id = tool.id if hasattr(tool, 'id') else str(tool)
397
+ tool_id = tool.id if hasattr(tool, "id") else str(tool)
388
398
  explanation = tool_explanations.get(tool_id, f"use {tool_id}")
389
399
  lines.append(f"• {explanation}")
390
400
 
@@ -418,7 +428,9 @@ class WorkflowExplainer:
418
428
  if self.audience == AudienceLevel.BEGINNER:
419
429
  lines.append(f"• {metric.name}: {metric.description}")
420
430
  else:
421
- target = f" (target: {metric.target_value})" if metric.target_value is not None else ""
431
+ target = (
432
+ f" (target: {metric.target_value})" if metric.target_value is not None else ""
433
+ )
422
434
  lines.append(f"• **{metric.name}**{target}: {metric.description}")
423
435
 
424
436
  return "\n".join(lines)
@@ -438,7 +450,10 @@ class WorkflowExplainer:
438
450
  f"to deliver results efficiently and consistently."
439
451
  )
440
452
  else:
441
- return blueprint.description or f"A {len(blueprint.stages)}-stage workflow for {blueprint.domain}."
453
+ return (
454
+ blueprint.description
455
+ or f"A {len(blueprint.stages)}-stage workflow for {blueprint.domain}."
456
+ )
442
457
 
443
458
  def generate_narrative(self, blueprint: WorkflowBlueprint) -> str:
444
459
  """Generate a narrative story-like explanation.
@@ -473,22 +488,16 @@ class WorkflowExplainer:
473
488
  lines.append(f"### Step {i}: {stage.name}")
474
489
  lines.append("")
475
490
 
476
- agents_in_stage = [
477
- agent_lookup[aid] for aid in stage.agent_ids if aid in agent_lookup
478
- ]
491
+ agents_in_stage = [agent_lookup[aid] for aid in stage.agent_ids if aid in agent_lookup]
479
492
 
480
493
  if stage.parallel and len(agents_in_stage) > 1:
481
494
  lines.append("Working in parallel:")
482
495
  for agent in agents_in_stage:
483
- role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(
484
- agent.role, "works"
485
- )
496
+ role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(agent.role, "works")
486
497
  lines.append(f"- **{agent.name}** {role_desc}")
487
498
  else:
488
499
  for agent in agents_in_stage:
489
- role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(
490
- agent.role, "works"
491
- )
500
+ role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(agent.role, "works")
492
501
  lines.append(f"**{agent.name}** {role_desc}.")
493
502
 
494
503
  lines.append("")
@@ -542,6 +551,7 @@ Format as markdown with clear sections."""
542
551
  if self._client is None and self.api_key:
543
552
  try:
544
553
  import anthropic
554
+
545
555
  self._client = anthropic.Anthropic(api_key=self.api_key)
546
556
  except ImportError:
547
557
  pass
@@ -571,13 +581,11 @@ Format as markdown with clear sections."""
571
581
 
572
582
  # Format workflow info for prompt
573
583
  agents_str = "\n".join(
574
- f"- {a.name} ({a.role.value}): {a.description}"
575
- for a in blueprint.agents
584
+ f"- {a.name} ({a.role.value}): {a.description}" for a in blueprint.agents
576
585
  )
577
586
 
578
587
  stages_str = "\n".join(
579
- f"- {s.name}: {', '.join(s.agent_ids)}"
580
- + (" (parallel)" if s.parallel else "")
588
+ f"- {s.name}: {', '.join(s.agent_ids)}" + (" (parallel)" if s.parallel else "")
581
589
  for s in blueprint.stages
582
590
  )
583
591
 
@@ -645,9 +653,10 @@ def explain_workflow(
645
653
  elif format == OutputFormat.TEXT:
646
654
  # Simple markdown to text conversion
647
655
  import re
648
- text = re.sub(r'#{1,6}\s+', '', markdown) # Remove headers
649
- text = re.sub(r'\*\*([^*]+)\*\*', r'\1', text) # Remove bold
650
- text = re.sub(r'\*([^*]+)\*', r'\1', text) # Remove italic
656
+
657
+ text = re.sub(r"#{1,6}\s+", "", markdown) # Remove headers
658
+ text = re.sub(r"\*\*([^*]+)\*\*", r"\1", text) # Remove bold
659
+ text = re.sub(r"\*([^*]+)\*", r"\1", text) # Remove italic
651
660
  return text
652
661
  elif format == OutputFormat.HTML:
653
662
  # Simple markdown to HTML
@@ -667,6 +676,7 @@ def explain_workflow(
667
676
  return explanation.to_html()
668
677
  elif format == OutputFormat.JSON:
669
678
  import json
679
+
670
680
  return json.dumps(explanation.to_dict(), indent=2)
671
681
  else:
672
682
  return explanation.to_markdown()