empathy-framework 4.6.2__py3-none-any.whl → 4.6.3__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 (53) hide show
  1. {empathy_framework-4.6.2.dist-info → empathy_framework-4.6.3.dist-info}/METADATA +1 -1
  2. {empathy_framework-4.6.2.dist-info → empathy_framework-4.6.3.dist-info}/RECORD +53 -20
  3. {empathy_framework-4.6.2.dist-info → empathy_framework-4.6.3.dist-info}/WHEEL +1 -1
  4. empathy_os/__init__.py +1 -1
  5. empathy_os/cli.py +361 -32
  6. empathy_os/config/xml_config.py +8 -3
  7. empathy_os/core.py +37 -4
  8. empathy_os/leverage_points.py +2 -1
  9. empathy_os/memory/short_term.py +45 -1
  10. empathy_os/meta_workflows/agent_creator 2.py +254 -0
  11. empathy_os/meta_workflows/builtin_templates 2.py +567 -0
  12. empathy_os/meta_workflows/cli_meta_workflows 2.py +1551 -0
  13. empathy_os/meta_workflows/form_engine 2.py +304 -0
  14. empathy_os/meta_workflows/intent_detector 2.py +298 -0
  15. empathy_os/meta_workflows/pattern_learner 2.py +754 -0
  16. empathy_os/meta_workflows/session_context 2.py +398 -0
  17. empathy_os/meta_workflows/template_registry 2.py +229 -0
  18. empathy_os/meta_workflows/workflow 2.py +980 -0
  19. empathy_os/models/token_estimator.py +16 -9
  20. empathy_os/models/validation.py +7 -1
  21. empathy_os/orchestration/pattern_learner 2.py +699 -0
  22. empathy_os/orchestration/real_tools 2.py +938 -0
  23. empathy_os/orchestration/real_tools.py +4 -2
  24. empathy_os/socratic/__init__ 2.py +273 -0
  25. empathy_os/socratic/ab_testing 2.py +969 -0
  26. empathy_os/socratic/blueprint 2.py +532 -0
  27. empathy_os/socratic/cli 2.py +689 -0
  28. empathy_os/socratic/collaboration 2.py +1112 -0
  29. empathy_os/socratic/domain_templates 2.py +916 -0
  30. empathy_os/socratic/embeddings 2.py +734 -0
  31. empathy_os/socratic/engine 2.py +729 -0
  32. empathy_os/socratic/explainer 2.py +663 -0
  33. empathy_os/socratic/feedback 2.py +767 -0
  34. empathy_os/socratic/forms 2.py +624 -0
  35. empathy_os/socratic/generator 2.py +716 -0
  36. empathy_os/socratic/llm_analyzer 2.py +635 -0
  37. empathy_os/socratic/mcp_server 2.py +751 -0
  38. empathy_os/socratic/session 2.py +306 -0
  39. empathy_os/socratic/storage 2.py +635 -0
  40. empathy_os/socratic/storage.py +2 -1
  41. empathy_os/socratic/success 2.py +719 -0
  42. empathy_os/socratic/visual_editor 2.py +812 -0
  43. empathy_os/socratic/web_ui 2.py +925 -0
  44. empathy_os/tier_recommender.py +5 -2
  45. empathy_os/workflow_commands.py +11 -6
  46. empathy_os/workflows/base.py +1 -1
  47. empathy_os/workflows/batch_processing 2.py +310 -0
  48. empathy_os/workflows/release_prep_crew 2.py +968 -0
  49. empathy_os/workflows/test_coverage_boost_crew 2.py +848 -0
  50. empathy_os/workflows/test_maintenance.py +3 -2
  51. {empathy_framework-4.6.2.dist-info → empathy_framework-4.6.3.dist-info}/entry_points.txt +0 -0
  52. {empathy_framework-4.6.2.dist-info → empathy_framework-4.6.3.dist-info}/licenses/LICENSE +0 -0
  53. {empathy_framework-4.6.2.dist-info → empathy_framework-4.6.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1551 @@
1
+ """CLI commands for meta-workflow system.
2
+
3
+ Provides command-line interface for:
4
+ - Listing available workflow templates
5
+ - Running meta-workflows
6
+ - Viewing analytics and insights
7
+ - Managing execution history
8
+
9
+ Usage:
10
+ empathy meta-workflow list-templates
11
+ empathy meta-workflow run <template_id>
12
+ empathy meta-workflow analytics [template_id]
13
+ empathy meta-workflow list-runs
14
+ empathy meta-workflow show <run_id>
15
+
16
+ Created: 2026-01-17
17
+ """
18
+
19
+ from datetime import datetime, timedelta
20
+ from pathlib import Path
21
+
22
+ import typer
23
+ from rich.console import Console
24
+ from rich.panel import Panel
25
+ from rich.table import Table
26
+ from rich.tree import Tree
27
+
28
+ from empathy_os.meta_workflows import (
29
+ MetaWorkflow,
30
+ PatternLearner,
31
+ TemplateRegistry,
32
+ list_execution_results,
33
+ load_execution_result,
34
+ )
35
+ from empathy_os.meta_workflows.intent_detector import IntentDetector
36
+
37
+ # Create Typer app for meta-workflow commands
38
+ meta_workflow_app = typer.Typer(
39
+ name="meta-workflow",
40
+ help="Meta-workflow system for dynamic agent team generation",
41
+ no_args_is_help=True,
42
+ )
43
+
44
+ console = Console()
45
+
46
+
47
+ # =============================================================================
48
+ # Template Commands
49
+ # =============================================================================
50
+
51
+
52
+ @meta_workflow_app.command("list-templates")
53
+ def list_templates(
54
+ storage_dir: str = typer.Option(
55
+ ".empathy/meta_workflows/templates",
56
+ "--storage-dir",
57
+ "-d",
58
+ help="Templates storage directory",
59
+ ),
60
+ ):
61
+ """List all available workflow templates.
62
+
63
+ Shows template metadata including:
64
+ - Template ID and name
65
+ - Description
66
+ - Estimated cost range
67
+ - Number of questions and agent rules
68
+ """
69
+ try:
70
+ registry = TemplateRegistry(storage_dir=storage_dir)
71
+ template_ids = registry.list_templates()
72
+
73
+ if not template_ids:
74
+ console.print("[yellow]No templates found.[/yellow]")
75
+ console.print(f"\nLooking in: {storage_dir}")
76
+ console.print("\nCreate templates by running workflow wizard or")
77
+ console.print("placing template JSON files in the templates directory.")
78
+ return
79
+
80
+ # Count built-in vs user templates
81
+ builtin_count = sum(1 for t in template_ids if registry.is_builtin(t))
82
+ user_count = len(template_ids) - builtin_count
83
+
84
+ console.print(f"\n[bold]Available Templates[/bold] ({len(template_ids)} total)")
85
+ console.print(f" [cyan]📦 Built-in:[/cyan] {builtin_count} [green]👤 User:[/green] {user_count}\n")
86
+
87
+ # Show migration hint for users coming from Crew workflows
88
+ if builtin_count > 0:
89
+ console.print("[dim]💡 Tip: Built-in templates replace deprecated Crew workflows.[/dim]")
90
+ console.print("[dim] See: empathy meta-workflow migrate --help[/dim]\n")
91
+
92
+ for template_id in template_ids:
93
+ template = registry.load_template(template_id)
94
+
95
+ if template:
96
+ # Add badge for built-in templates
97
+ is_builtin = registry.is_builtin(template_id)
98
+ badge = "[cyan]📦 BUILT-IN[/cyan]" if is_builtin else "[green]👤 USER[/green]"
99
+
100
+ # Create info panel
101
+ info_lines = [
102
+ f"[bold]{template.name}[/bold] {badge}",
103
+ f"[dim]{template.description}[/dim]",
104
+ "",
105
+ f"ID: {template.template_id}",
106
+ f"Version: {template.version}",
107
+ f"Author: {template.author}",
108
+ f"Tags: {', '.join(template.tags)}",
109
+ "",
110
+ f"Questions: {len(template.form_schema.questions)}",
111
+ f"Agent Rules: {len(template.agent_composition_rules)}",
112
+ "",
113
+ f"Est. Cost: ${template.estimated_cost_range[0]:.2f}-${template.estimated_cost_range[1]:.2f}",
114
+ f"Est. Duration: ~{template.estimated_duration_minutes} min",
115
+ ]
116
+
117
+ # Add quick start command
118
+ info_lines.append("")
119
+ info_lines.append(f"[bold]Quick Start:[/bold] empathy meta-workflow run {template_id}")
120
+
121
+ console.print(Panel("\n".join(info_lines), border_style="blue" if is_builtin else "green"))
122
+ console.print()
123
+
124
+ except Exception as e:
125
+ console.print(f"[red]Error:[/red] {e}")
126
+ raise typer.Exit(code=1)
127
+
128
+
129
+ @meta_workflow_app.command("inspect")
130
+ def inspect_template(
131
+ template_id: str = typer.Argument(..., help="Template ID to inspect"),
132
+ storage_dir: str = typer.Option(
133
+ ".empathy/meta_workflows/templates",
134
+ "--storage-dir",
135
+ "-d",
136
+ help="Templates storage directory",
137
+ ),
138
+ show_rules: bool = typer.Option(
139
+ False,
140
+ "--show-rules",
141
+ "-r",
142
+ help="Show agent composition rules",
143
+ ),
144
+ ):
145
+ """Inspect a specific template in detail.
146
+
147
+ Shows comprehensive template information including:
148
+ - Form questions and types
149
+ - Agent composition rules (optional)
150
+ - Configuration mappings
151
+ """
152
+ try:
153
+ registry = TemplateRegistry(storage_dir=storage_dir)
154
+ template = registry.load_template(template_id)
155
+
156
+ if not template:
157
+ console.print(f"[red]Template not found:[/red] {template_id}")
158
+ raise typer.Exit(code=1)
159
+
160
+ # Header
161
+ console.print(f"\n[bold cyan]Template: {template.name}[/bold cyan]")
162
+ console.print(f"[dim]{template.description}[/dim]\n")
163
+
164
+ # Form Schema
165
+ console.print("[bold]Form Questions:[/bold]")
166
+ form_tree = Tree("📋 Questions")
167
+
168
+ for i, question in enumerate(template.form_schema.questions, 1):
169
+ question_text = f"[cyan]{question.text}[/cyan]"
170
+ q_node = form_tree.add(f"{i}. {question_text}")
171
+ q_node.add(f"ID: {question.id}")
172
+ q_node.add(f"Type: {question.type.value}")
173
+ if question.options:
174
+ options_str = ", ".join(question.options[:3])
175
+ if len(question.options) > 3:
176
+ options_str += f", ... ({len(question.options) - 3} more)"
177
+ q_node.add(f"Options: {options_str}")
178
+ if question.required:
179
+ q_node.add("[yellow]Required[/yellow]")
180
+ if question.default:
181
+ q_node.add(f"Default: {question.default}")
182
+
183
+ console.print(form_tree)
184
+
185
+ # Agent Composition Rules (optional)
186
+ if show_rules:
187
+ console.print(f"\n[bold]Agent Composition Rules:[/bold] ({len(template.agent_composition_rules)})\n")
188
+
189
+ for i, rule in enumerate(template.agent_composition_rules, 1):
190
+ rule_lines = [
191
+ f"[bold cyan]{i}. {rule.role}[/bold cyan]",
192
+ f" Base Template: {rule.base_template}",
193
+ f" Tier Strategy: {rule.tier_strategy.value}",
194
+ f" Tools: {', '.join(rule.tools) if rule.tools else 'None'}",
195
+ ]
196
+
197
+ if rule.required_responses:
198
+ rule_lines.append(f" Required When: {rule.required_responses}")
199
+
200
+ if rule.config_mapping:
201
+ rule_lines.append(f" Config Mapping: {len(rule.config_mapping)} fields")
202
+
203
+ console.print("\n".join(rule_lines))
204
+ console.print()
205
+
206
+ # Summary
207
+ console.print("\n[bold]Summary:[/bold]")
208
+ console.print(f" Questions: {len(template.form_schema.questions)}")
209
+ console.print(f" Agent Rules: {len(template.agent_composition_rules)}")
210
+ console.print(f" Estimated Cost: ${template.estimated_cost_range[0]:.2f}-${template.estimated_cost_range[1]:.2f}")
211
+ console.print()
212
+
213
+ except Exception as e:
214
+ console.print(f"[red]Error:[/red] {e}")
215
+ raise typer.Exit(code=1)
216
+
217
+
218
+ # =============================================================================
219
+ # Execution Commands
220
+ # =============================================================================
221
+
222
+
223
+ @meta_workflow_app.command("run")
224
+ def run_workflow(
225
+ template_id: str = typer.Argument(..., help="Template ID to execute"),
226
+ mock: bool = typer.Option(
227
+ True,
228
+ "--mock/--real",
229
+ help="Use mock execution (for testing)",
230
+ ),
231
+ use_memory: bool = typer.Option(
232
+ False,
233
+ "--use-memory",
234
+ "-m",
235
+ help="Enable memory integration for enhanced analytics",
236
+ ),
237
+ use_defaults: bool = typer.Option(
238
+ False,
239
+ "--use-defaults",
240
+ "-d",
241
+ help="Use default values instead of asking questions (non-interactive mode)",
242
+ ),
243
+ user_id: str = typer.Option(
244
+ "cli_user",
245
+ "--user-id",
246
+ "-u",
247
+ help="User ID for memory integration",
248
+ ),
249
+ ):
250
+ """Execute a meta-workflow from template.
251
+
252
+ This will:
253
+ 1. Load the template
254
+ 2. Ask form questions interactively (or use defaults with --use-defaults)
255
+ 3. Generate dynamic agent team
256
+ 4. Execute agents (mock or real)
257
+ 5. Save results (files + optional memory)
258
+ 6. Display summary
259
+
260
+ Examples:
261
+ empathy meta-workflow run release-prep
262
+ empathy meta-workflow run test-coverage-boost --real
263
+ empathy meta-workflow run manage-docs --use-defaults
264
+ """
265
+ try:
266
+ # Load template
267
+ console.print(f"\n[bold]Loading template:[/bold] {template_id}")
268
+ registry = TemplateRegistry()
269
+ template = registry.load_template(template_id)
270
+
271
+ if not template:
272
+ console.print(f"[red]Template not found:[/red] {template_id}")
273
+ raise typer.Exit(code=1)
274
+
275
+ console.print(f"[green]✓[/green] {template.name}")
276
+
277
+ # Setup memory if requested
278
+ pattern_learner = None
279
+ if use_memory:
280
+ console.print("\n[bold]Initializing memory integration...[/bold]")
281
+ from empathy_os.memory.unified import UnifiedMemory
282
+
283
+ try:
284
+ memory = UnifiedMemory(user_id=user_id)
285
+ pattern_learner = PatternLearner(memory=memory)
286
+ console.print("[green]✓[/green] Memory enabled")
287
+ except Exception as e:
288
+ console.print(f"[yellow]Warning:[/yellow] Memory initialization failed: {e}")
289
+ console.print("[yellow]Continuing without memory integration[/yellow]")
290
+
291
+ # Create workflow
292
+ workflow = MetaWorkflow(
293
+ template=template,
294
+ pattern_learner=pattern_learner,
295
+ )
296
+
297
+ # Execute (will ask questions via AskUserQuestion unless --use-defaults)
298
+ console.print("\n[bold]Executing workflow...[/bold]")
299
+ console.print(f"Mode: {'Mock' if mock else 'Real'}")
300
+ if use_defaults:
301
+ console.print("[cyan]Using default values (non-interactive)[/cyan]")
302
+
303
+ result = workflow.execute(mock_execution=mock, use_defaults=use_defaults)
304
+
305
+ # Display summary
306
+ console.print("\n[bold green]Execution Complete![/bold green]\n")
307
+
308
+ summary_lines = [
309
+ f"[bold]Run ID:[/bold] {result.run_id}",
310
+ f"[bold]Status:[/bold] {'✅ Success' if result.success else '❌ Failed'}",
311
+ "",
312
+ f"[bold]Agents Created:[/bold] {len(result.agents_created)}",
313
+ f"[bold]Agents Executed:[/bold] {len(result.agent_results)}",
314
+ f"[bold]Total Cost:[/bold] ${result.total_cost:.2f}",
315
+ f"[bold]Duration:[/bold] {result.total_duration:.1f}s",
316
+ ]
317
+
318
+ if result.error:
319
+ summary_lines.append(f"\n[bold red]Error:[/bold red] {result.error}")
320
+
321
+ console.print(Panel("\n".join(summary_lines), title="Execution Summary", border_style="green"))
322
+
323
+ # Show agents
324
+ console.print("\n[bold]Agents Executed:[/bold]\n")
325
+
326
+ for agent_result in result.agent_results:
327
+ status = "✅" if agent_result.success else "❌"
328
+ console.print(
329
+ f" {status} [cyan]{agent_result.role}[/cyan] "
330
+ f"(tier: {agent_result.tier_used}, cost: ${agent_result.cost:.2f})"
331
+ )
332
+
333
+ # Show where results saved
334
+ console.print("\n[bold]Results saved to:[/bold]")
335
+ console.print(f" 📁 Files: .empathy/meta_workflows/executions/{result.run_id}/")
336
+ if use_memory and pattern_learner and pattern_learner.memory:
337
+ console.print(" 🧠 Memory: Long-term storage")
338
+
339
+ console.print(f"\n[dim]View details: empathy meta-workflow show {result.run_id}[/dim]")
340
+ console.print()
341
+
342
+ except Exception as e:
343
+ console.print(f"\n[red]Error:[/red] {e}")
344
+ import traceback
345
+ traceback.print_exc()
346
+ raise typer.Exit(code=1)
347
+
348
+
349
+ @meta_workflow_app.command("ask")
350
+ def natural_language_run(
351
+ request: str = typer.Argument(..., help="Natural language description of what you need"),
352
+ auto_run: bool = typer.Option(
353
+ False,
354
+ "--auto",
355
+ "-a",
356
+ help="Automatically run if high confidence match (>60%)",
357
+ ),
358
+ mock: bool = typer.Option(
359
+ True,
360
+ "--mock/--real",
361
+ help="Use mock execution (for testing)",
362
+ ),
363
+ use_defaults: bool = typer.Option(
364
+ True,
365
+ "--use-defaults/--interactive",
366
+ "-d/-i",
367
+ help="Use default values (non-interactive)",
368
+ ),
369
+ ):
370
+ """Create agent teams using natural language.
371
+
372
+ Analyzes your request and suggests appropriate agent teams.
373
+ Use --auto to automatically run the best match.
374
+
375
+ Examples:
376
+ empathy meta-workflow ask "I need to prepare for a release"
377
+ empathy meta-workflow ask "improve my test coverage" --auto --real
378
+ empathy meta-workflow ask "check if documentation is up to date"
379
+ """
380
+ try:
381
+ detector = IntentDetector()
382
+ matches = detector.detect(request)
383
+
384
+ if not matches:
385
+ console.print("\n[yellow]I couldn't identify a matching agent team for your request.[/yellow]")
386
+ console.print("\n[bold]Available agent teams:[/bold]")
387
+ console.print(" • [cyan]release-prep[/cyan] - Security, testing, code quality, documentation checks")
388
+ console.print(" • [cyan]test-coverage-boost[/cyan] - Analyze and improve test coverage")
389
+ console.print(" • [cyan]test-maintenance[/cyan] - Test lifecycle management")
390
+ console.print(" • [cyan]manage-docs[/cyan] - Documentation sync and gap detection")
391
+ console.print("\n[dim]Try: empathy meta-workflow run <template-id>[/dim]\n")
392
+ return
393
+
394
+ # Show detected matches
395
+ console.print(f"\n[bold]Analyzing:[/bold] \"{request}\"\n")
396
+
397
+ best_match = matches[0]
398
+ confidence_pct = int(best_match.confidence * 100)
399
+
400
+ # If auto-run and high confidence, run immediately
401
+ if auto_run and best_match.confidence >= 0.6:
402
+ console.print(f"[bold green]Auto-detected:[/bold green] {best_match.template_name} ({confidence_pct}% confidence)")
403
+ console.print(f"[dim]{best_match.description}[/dim]\n")
404
+ console.print(f"[bold]Running {best_match.template_id}...[/bold]\n")
405
+
406
+ # Run the workflow
407
+ ctx = typer.Context(run_workflow)
408
+ run_workflow(
409
+ template_id=best_match.template_id,
410
+ mock=mock,
411
+ use_memory=False,
412
+ use_defaults=use_defaults,
413
+ user_id="cli_user",
414
+ )
415
+ return
416
+
417
+ # Show suggestions
418
+ console.print("[bold]Suggested Agent Teams:[/bold]\n")
419
+
420
+ for i, match in enumerate(matches[:3], 1):
421
+ confidence = int(match.confidence * 100)
422
+ style = "green" if match.confidence >= 0.6 else "yellow" if match.confidence >= 0.4 else "dim"
423
+
424
+ console.print(f" {i}. [{style}]{match.template_name}[/{style}] ({confidence}% match)")
425
+ console.print(f" [dim]{match.description}[/dim]")
426
+ if match.matched_keywords:
427
+ keywords = ", ".join(match.matched_keywords[:5])
428
+ console.print(f" [dim]Matched: {keywords}[/dim]")
429
+ console.print(f" Run: [cyan]empathy meta-workflow run {match.template_id}[/cyan]")
430
+ console.print()
431
+
432
+ # Prompt to run best match
433
+ if best_match.confidence >= 0.5:
434
+ console.print("[bold]Quick Run:[/bold] Use [cyan]--auto[/cyan] to automatically run the best match")
435
+ console.print(f"[dim]Example: empathy meta-workflow ask \"{request}\" --auto --real[/dim]\n")
436
+
437
+ except Exception as e:
438
+ console.print(f"[red]Error:[/red] {e}")
439
+ raise typer.Exit(code=1)
440
+
441
+
442
+ @meta_workflow_app.command("detect")
443
+ def detect_intent(
444
+ request: str = typer.Argument(..., help="Natural language request to analyze"),
445
+ threshold: float = typer.Option(
446
+ 0.3,
447
+ "--threshold",
448
+ "-t",
449
+ help="Minimum confidence threshold (0.0-1.0)",
450
+ ),
451
+ ):
452
+ """Detect intent from natural language without running.
453
+
454
+ Useful for testing what agent teams would be suggested for a given request.
455
+
456
+ Examples:
457
+ empathy meta-workflow detect "check security vulnerabilities"
458
+ empathy meta-workflow detect "generate more tests" --threshold 0.5
459
+ """
460
+ try:
461
+ detector = IntentDetector()
462
+ matches = detector.detect(request, threshold=threshold)
463
+
464
+ console.print(f"\n[bold]Intent Analysis:[/bold] \"{request}\"\n")
465
+ console.print(f"[dim]Threshold: {threshold:.0%}[/dim]\n")
466
+
467
+ if not matches:
468
+ console.print("[yellow]No matches above threshold.[/yellow]\n")
469
+ return
470
+
471
+ # Create table
472
+ table = Table(show_header=True)
473
+ table.add_column("Template", style="cyan")
474
+ table.add_column("Confidence", justify="right")
475
+ table.add_column("Matched Keywords")
476
+ table.add_column("Would Auto-Run?")
477
+
478
+ for match in matches:
479
+ confidence = f"{match.confidence:.0%}"
480
+ keywords = ", ".join(match.matched_keywords[:4])
481
+ auto_run = "✅ Yes" if match.confidence >= 0.6 else "❌ No"
482
+
483
+ table.add_row(
484
+ match.template_id,
485
+ confidence,
486
+ keywords or "-",
487
+ auto_run,
488
+ )
489
+
490
+ console.print(table)
491
+ console.print()
492
+
493
+ except Exception as e:
494
+ console.print(f"[red]Error:[/red] {e}")
495
+ raise typer.Exit(code=1)
496
+
497
+
498
+ # =============================================================================
499
+ # Analytics Commands
500
+ # =============================================================================
501
+
502
+
503
+ @meta_workflow_app.command("analytics")
504
+ def show_analytics(
505
+ template_id: str | None = typer.Argument(
506
+ None,
507
+ help="Template ID to analyze (optional, all if not specified)",
508
+ ),
509
+ min_confidence: float = typer.Option(
510
+ 0.5,
511
+ "--min-confidence",
512
+ "-c",
513
+ help="Minimum confidence threshold (0.0-1.0)",
514
+ ),
515
+ use_memory: bool = typer.Option(
516
+ False,
517
+ "--use-memory",
518
+ "-m",
519
+ help="Use memory-enhanced analytics",
520
+ ),
521
+ ):
522
+ """Show pattern learning analytics and recommendations.
523
+
524
+ Displays:
525
+ - Execution statistics
526
+ - Tier performance insights
527
+ - Cost analysis
528
+ - Recommendations
529
+ """
530
+ try:
531
+ # Initialize pattern learner
532
+ pattern_learner = PatternLearner()
533
+
534
+ if use_memory:
535
+ console.print("[bold]Initializing memory-enhanced analytics...[/bold]\n")
536
+ from empathy_os.memory.unified import UnifiedMemory
537
+ memory = UnifiedMemory(user_id="cli_analytics")
538
+ pattern_learner = PatternLearner(memory=memory)
539
+
540
+ # Generate report
541
+ report = pattern_learner.generate_analytics_report(template_id=template_id)
542
+
543
+ # Display summary
544
+ summary = report["summary"]
545
+
546
+ console.print("\n[bold cyan]Meta-Workflow Analytics Report[/bold cyan]")
547
+ if template_id:
548
+ console.print(f"[dim]Template: {template_id}[/dim]")
549
+ console.print()
550
+
551
+ summary_table = Table(show_header=False, box=None)
552
+ summary_table.add_column("Metric", style="bold")
553
+ summary_table.add_column("Value")
554
+
555
+ summary_table.add_row("Total Runs", str(summary["total_runs"]))
556
+ summary_table.add_row(
557
+ "Successful",
558
+ f"{summary['successful_runs']} ({summary['success_rate']:.0%})"
559
+ )
560
+ summary_table.add_row("Total Cost", f"${summary['total_cost']:.2f}")
561
+ summary_table.add_row("Avg Cost/Run", f"${summary['avg_cost_per_run']:.2f}")
562
+ summary_table.add_row("Total Agents", str(summary["total_agents_created"]))
563
+ summary_table.add_row("Avg Agents/Run", f"{summary['avg_agents_per_run']:.1f}")
564
+
565
+ console.print(Panel(summary_table, title="Summary", border_style="cyan"))
566
+
567
+ # Recommendations
568
+ recommendations = report.get("recommendations", [])
569
+ if recommendations:
570
+ console.print("\n[bold]Recommendations:[/bold]\n")
571
+ for rec in recommendations:
572
+ console.print(f" {rec}")
573
+
574
+ # Insights
575
+ insights = report.get("insights", {})
576
+
577
+ if insights.get("tier_performance"):
578
+ console.print("\n[bold]Tier Performance:[/bold]\n")
579
+ for insight in insights["tier_performance"][:5]: # Top 5
580
+ console.print(f" • {insight['description']}")
581
+ console.print(f" [dim]Confidence: {insight['confidence']:.0%} (n={insight['sample_size']})[/dim]")
582
+
583
+ if insights.get("cost_analysis"):
584
+ console.print("\n[bold]Cost Analysis:[/bold]\n")
585
+ for insight in insights["cost_analysis"]:
586
+ console.print(f" • {insight['description']}")
587
+
588
+ # Tier breakdown
589
+ breakdown = insight['data'].get('tier_breakdown', {})
590
+ if breakdown:
591
+ console.print("\n [dim]By Tier:[/dim]")
592
+ for tier, stats in breakdown.items():
593
+ console.print(
594
+ f" {tier}: ${stats['avg']:.2f} avg "
595
+ f"(${stats['total']:.2f} total, {stats['count']} runs)"
596
+ )
597
+
598
+ if insights.get("failure_analysis"):
599
+ console.print("\n[bold yellow]Failure Analysis:[/bold yellow]\n")
600
+ for insight in insights["failure_analysis"]:
601
+ console.print(f" ⚠️ {insight['description']}")
602
+
603
+ console.print()
604
+
605
+ except Exception as e:
606
+ console.print(f"[red]Error:[/red] {e}")
607
+ raise typer.Exit(code=1)
608
+
609
+
610
+ # =============================================================================
611
+ # Execution History Commands
612
+ # =============================================================================
613
+
614
+
615
+ @meta_workflow_app.command("list-runs")
616
+ def list_runs(
617
+ template_id: str | None = typer.Option(
618
+ None,
619
+ "--template",
620
+ "-t",
621
+ help="Filter by template ID",
622
+ ),
623
+ limit: int = typer.Option(
624
+ 10,
625
+ "--limit",
626
+ "-n",
627
+ help="Maximum number of results",
628
+ ),
629
+ ):
630
+ """List execution history.
631
+
632
+ Shows recent workflow executions with:
633
+ - Run ID and timestamp
634
+ - Template name
635
+ - Success status
636
+ - Cost and duration
637
+ """
638
+ try:
639
+ run_ids = list_execution_results()
640
+
641
+ if not run_ids:
642
+ console.print("[yellow]No execution results found.[/yellow]")
643
+ return
644
+
645
+ console.print(f"\n[bold]Recent Executions[/bold] (showing {min(limit, len(run_ids))} of {len(run_ids)}):\n")
646
+
647
+ # Create table
648
+ table = Table(show_header=True)
649
+ table.add_column("Run ID", style="cyan")
650
+ table.add_column("Template")
651
+ table.add_column("Status")
652
+ table.add_column("Cost", justify="right")
653
+ table.add_column("Duration", justify="right")
654
+ table.add_column("Timestamp")
655
+
656
+ count = 0
657
+ for run_id in run_ids[:limit]:
658
+ try:
659
+ result = load_execution_result(run_id)
660
+
661
+ # Filter by template if specified
662
+ if template_id and result.template_id != template_id:
663
+ continue
664
+
665
+ status = "✅" if result.success else "❌"
666
+ cost = f"${result.total_cost:.2f}"
667
+ duration = f"{result.total_duration:.1f}s"
668
+
669
+ # Parse timestamp
670
+ try:
671
+ ts = datetime.fromisoformat(result.timestamp)
672
+ timestamp = ts.strftime("%Y-%m-%d %H:%M")
673
+ except Exception:
674
+ timestamp = result.timestamp[:16]
675
+
676
+ table.add_row(
677
+ run_id,
678
+ result.template_id,
679
+ status,
680
+ cost,
681
+ duration,
682
+ timestamp,
683
+ )
684
+
685
+ count += 1
686
+
687
+ except Exception as e:
688
+ console.print(f"[yellow]Warning:[/yellow] Failed to load {run_id}: {e}")
689
+ continue
690
+
691
+ if count == 0:
692
+ if template_id:
693
+ console.print(f"[yellow]No executions found for template: {template_id}[/yellow]")
694
+ else:
695
+ console.print("[yellow]No valid execution results found.[/yellow]")
696
+ return
697
+
698
+ console.print(table)
699
+ console.print("\n[dim]View details: empathy meta-workflow show <run_id>[/dim]\n")
700
+
701
+ except Exception as e:
702
+ console.print(f"[red]Error:[/red] {e}")
703
+ raise typer.Exit(code=1)
704
+
705
+
706
+ @meta_workflow_app.command("show")
707
+ def show_execution(
708
+ run_id: str = typer.Argument(..., help="Run ID to display"),
709
+ format: str = typer.Option(
710
+ "text",
711
+ "--format",
712
+ "-f",
713
+ help="Output format (text or json)",
714
+ ),
715
+ ):
716
+ """Show detailed execution report.
717
+
718
+ Displays comprehensive information about a specific workflow execution:
719
+ - Form responses
720
+ - Agents created and executed
721
+ - Cost breakdown
722
+ - Success/failure details
723
+ """
724
+ try:
725
+ result = load_execution_result(run_id)
726
+
727
+ if format == "json":
728
+ # JSON output
729
+ print(result.to_json())
730
+ return
731
+
732
+ # Text format (default)
733
+ console.print(f"\n[bold cyan]Execution Report: {run_id}[/bold cyan]\n")
734
+
735
+ # Status
736
+ status = "✅ Success" if result.success else "❌ Failed"
737
+ console.print(f"[bold]Status:[/bold] {status}")
738
+ console.print(f"[bold]Template:[/bold] {result.template_id}")
739
+ console.print(f"[bold]Timestamp:[/bold] {result.timestamp}")
740
+
741
+ if result.error:
742
+ console.print(f"\n[bold red]Error:[/bold red] {result.error}\n")
743
+
744
+ # Summary
745
+ console.print("\n[bold]Summary:[/bold]")
746
+ console.print(f" Agents Created: {len(result.agents_created)}")
747
+ console.print(f" Agents Executed: {len(result.agent_results)}")
748
+ console.print(f" Total Cost: ${result.total_cost:.2f}")
749
+ console.print(f" Duration: {result.total_duration:.1f}s")
750
+
751
+ # Form Responses
752
+ console.print("\n[bold]Form Responses:[/bold]\n")
753
+ for key, value in result.form_responses.responses.items():
754
+ console.print(f" [cyan]{key}:[/cyan] {value}")
755
+
756
+ # Agents
757
+ console.print("\n[bold]Agents Executed:[/bold]\n")
758
+ for i, agent_result in enumerate(result.agent_results, 1):
759
+ status_emoji = "✅" if agent_result.success else "❌"
760
+ console.print(f" {i}. {status_emoji} [cyan]{agent_result.role}[/cyan]")
761
+ console.print(f" Tier: {agent_result.tier_used}")
762
+ console.print(f" Cost: ${agent_result.cost:.2f}")
763
+ console.print(f" Duration: {agent_result.duration:.1f}s")
764
+ if agent_result.error:
765
+ console.print(f" [red]Error: {agent_result.error}[/red]")
766
+ console.print()
767
+
768
+ # Cost breakdown
769
+ console.print("[bold]Cost Breakdown by Tier:[/bold]\n")
770
+ tier_costs = {}
771
+ for agent_result in result.agent_results:
772
+ tier = agent_result.tier_used
773
+ tier_costs[tier] = tier_costs.get(tier, 0.0) + agent_result.cost
774
+
775
+ for tier, cost in sorted(tier_costs.items()):
776
+ console.print(f" {tier}: ${cost:.2f}")
777
+
778
+ console.print()
779
+
780
+ except FileNotFoundError:
781
+ console.print(f"[red]Execution not found:[/red] {run_id}")
782
+ console.print("\n[dim]List available runs: empathy meta-workflow list-runs[/dim]")
783
+ raise typer.Exit(code=1)
784
+ except Exception as e:
785
+ console.print(f"[red]Error:[/red] {e}")
786
+ raise typer.Exit(code=1)
787
+
788
+
789
+ # =============================================================================
790
+ # Maintenance Commands
791
+ # =============================================================================
792
+
793
+
794
+ @meta_workflow_app.command("cleanup")
795
+ def cleanup_executions(
796
+ older_than_days: int = typer.Option(
797
+ 30,
798
+ "--older-than",
799
+ "-d",
800
+ help="Delete executions older than N days",
801
+ ),
802
+ dry_run: bool = typer.Option(
803
+ False,
804
+ "--dry-run",
805
+ help="Show what would be deleted without deleting",
806
+ ),
807
+ template_id: str | None = typer.Option(
808
+ None,
809
+ "--template",
810
+ "-t",
811
+ help="Filter by template ID",
812
+ ),
813
+ ):
814
+ """Clean up old execution results.
815
+
816
+ Deletes execution directories older than the specified number of days.
817
+ Use --dry-run to preview what would be deleted.
818
+ """
819
+ try:
820
+ cutoff_date = datetime.now() - timedelta(days=older_than_days)
821
+
822
+ run_ids = list_execution_results()
823
+
824
+ if not run_ids:
825
+ console.print("[yellow]No execution results found.[/yellow]")
826
+ return
827
+
828
+ to_delete = []
829
+
830
+ for run_id in run_ids:
831
+ try:
832
+ result = load_execution_result(run_id)
833
+
834
+ # Filter by template if specified
835
+ if template_id and result.template_id != template_id:
836
+ continue
837
+
838
+ # Parse timestamp
839
+ ts = datetime.fromisoformat(result.timestamp)
840
+
841
+ if ts < cutoff_date:
842
+ to_delete.append((run_id, result, ts))
843
+
844
+ except Exception as e:
845
+ console.print(f"[yellow]Warning:[/yellow] Failed to load {run_id}: {e}")
846
+ continue
847
+
848
+ if not to_delete:
849
+ console.print(
850
+ f"[green]No executions older than {older_than_days} days found.[/green]"
851
+ )
852
+ return
853
+
854
+ # Show what will be deleted
855
+ console.print(f"\n[bold]Executions to delete:[/bold] ({len(to_delete)})\n")
856
+
857
+ table = Table(show_header=True)
858
+ table.add_column("Run ID", style="cyan")
859
+ table.add_column("Template")
860
+ table.add_column("Age (days)", justify="right")
861
+ table.add_column("Cost", justify="right")
862
+
863
+ total_cost_saved = 0.0
864
+ for run_id, result, ts in to_delete:
865
+ age_days = (datetime.now() - ts).days
866
+ table.add_row(
867
+ run_id,
868
+ result.template_id,
869
+ str(age_days),
870
+ f"${result.total_cost:.2f}",
871
+ )
872
+ total_cost_saved += result.total_cost
873
+
874
+ console.print(table)
875
+ console.print(f"\nTotal cost represented: ${total_cost_saved:.2f}")
876
+
877
+ if dry_run:
878
+ console.print("\n[yellow]DRY RUN - No files deleted[/yellow]")
879
+ console.print(f"Run without --dry-run to delete {len(to_delete)} executions")
880
+ return
881
+
882
+ # Confirm deletion
883
+ if not typer.confirm(f"\nDelete {len(to_delete)} execution(s)?"):
884
+ console.print("[yellow]Cancelled[/yellow]")
885
+ return
886
+
887
+ # Delete
888
+ import shutil
889
+ deleted = 0
890
+ for run_id, _, _ in to_delete:
891
+ try:
892
+ run_dir = Path.home() / ".empathy" / "meta_workflows" / "executions" / run_id
893
+ if run_dir.exists():
894
+ shutil.rmtree(run_dir)
895
+ deleted += 1
896
+ except Exception as e:
897
+ console.print(f"[red]Failed to delete {run_id}:[/red] {e}")
898
+
899
+ console.print(f"\n[green]✓ Deleted {deleted} execution(s)[/green]\n")
900
+
901
+ except Exception as e:
902
+ console.print(f"[red]Error:[/red] {e}")
903
+ raise typer.Exit(code=1)
904
+
905
+
906
+ # =============================================================================
907
+ # Memory Search Commands
908
+ # =============================================================================
909
+
910
+
911
+ @meta_workflow_app.command("search-memory")
912
+ def search_memory(
913
+ query: str = typer.Argument(..., help="Search query for patterns"),
914
+ pattern_type: str | None = typer.Option(
915
+ None,
916
+ "--type",
917
+ "-t",
918
+ help="Filter by pattern type (e.g., 'meta_workflow_execution')",
919
+ ),
920
+ limit: int = typer.Option(
921
+ 10,
922
+ "--limit",
923
+ "-l",
924
+ help="Maximum number of results to return",
925
+ ),
926
+ user_id: str = typer.Option(
927
+ "cli_user",
928
+ "--user-id",
929
+ "-u",
930
+ help="User ID for memory access",
931
+ ),
932
+ ):
933
+ """Search memory for patterns using keyword matching.
934
+
935
+ Searches long-term memory for patterns matching the query.
936
+ Uses relevance scoring: exact phrase (10 pts), keyword in content (2 pts),
937
+ keyword in metadata (1 pt).
938
+
939
+ Examples:
940
+ empathy meta-workflow search-memory "successful workflow"
941
+ empathy meta-workflow search-memory "test coverage" --type meta_workflow_execution
942
+ empathy meta-workflow search-memory "error" --limit 20
943
+ """
944
+ try:
945
+ from empathy_os.memory.unified import UnifiedMemory
946
+
947
+ console.print(f"\n[bold]Searching memory for:[/bold] '{query}'")
948
+ if pattern_type:
949
+ console.print(f"[dim]Pattern type: {pattern_type}[/dim]")
950
+ console.print()
951
+
952
+ # Initialize memory
953
+ memory = UnifiedMemory(user_id=user_id)
954
+
955
+ # Search
956
+ results = memory.search_patterns(
957
+ query=query,
958
+ pattern_type=pattern_type,
959
+ limit=limit,
960
+ )
961
+
962
+ if not results:
963
+ console.print("[yellow]No matching patterns found.[/yellow]\n")
964
+ return
965
+
966
+ # Display results
967
+ console.print(f"[green]Found {len(results)} matching pattern(s):[/green]\n")
968
+
969
+ for i, pattern in enumerate(results, 1):
970
+ panel = Panel(
971
+ f"[bold]Pattern ID:[/bold] {pattern.get('pattern_id', 'N/A')}\n"
972
+ f"[bold]Type:[/bold] {pattern.get('pattern_type', 'N/A')}\n"
973
+ f"[bold]Classification:[/bold] {pattern.get('classification', 'N/A')}\n\n"
974
+ f"[bold]Content:[/bold]\n{str(pattern.get('content', 'N/A'))[:200]}...\n\n"
975
+ f"[bold]Metadata:[/bold] {pattern.get('metadata', {})}",
976
+ title=f"Result {i}/{len(results)}",
977
+ border_style="blue",
978
+ )
979
+ console.print(panel)
980
+ console.print()
981
+
982
+ except ImportError:
983
+ console.print(
984
+ "[red]Error:[/red] UnifiedMemory not available. "
985
+ "Ensure memory module is installed."
986
+ )
987
+ raise typer.Exit(code=1)
988
+ except Exception as e:
989
+ console.print(f"[red]Error:[/red] {e}")
990
+ raise typer.Exit(code=1)
991
+
992
+
993
+ # =============================================================================
994
+ # Session Context Commands
995
+ # =============================================================================
996
+
997
+
998
+ @meta_workflow_app.command("session-stats")
999
+ def show_session_stats(
1000
+ session_id: str | None = typer.Option(
1001
+ None,
1002
+ "--session-id",
1003
+ "-s",
1004
+ help="Session ID (optional, creates new if not specified)",
1005
+ ),
1006
+ user_id: str = typer.Option(
1007
+ "cli_user",
1008
+ "--user-id",
1009
+ "-u",
1010
+ help="User ID for session",
1011
+ ),
1012
+ ):
1013
+ """Show session context statistics.
1014
+
1015
+ Displays information about user's session including:
1016
+ - Recent form choices
1017
+ - Templates used
1018
+ - Choice counts
1019
+
1020
+ Examples:
1021
+ empathy meta-workflow session-stats
1022
+ empathy meta-workflow session-stats --session-id sess_123
1023
+ """
1024
+ try:
1025
+ from empathy_os.memory.unified import UnifiedMemory
1026
+ from empathy_os.meta_workflows.session_context import SessionContext
1027
+
1028
+ # Initialize memory and session
1029
+ memory = UnifiedMemory(user_id=user_id)
1030
+ session = SessionContext(
1031
+ memory=memory,
1032
+ session_id=session_id,
1033
+ )
1034
+
1035
+ console.print("\n[bold]Session Statistics[/bold]")
1036
+ console.print(f"[dim]Session ID: {session.session_id}[/dim]")
1037
+ console.print(f"[dim]User ID: {session.user_id}[/dim]\n")
1038
+
1039
+ # Get stats
1040
+ stats = session.get_session_stats()
1041
+
1042
+ # Display
1043
+ table = Table(show_header=True)
1044
+ table.add_column("Metric", style="cyan")
1045
+ table.add_column("Value")
1046
+
1047
+ table.add_row("Total Choices", str(stats.get("choice_count", 0)))
1048
+ table.add_row("Templates Used", str(len(stats.get("templates_used", []))))
1049
+ table.add_row(
1050
+ "Most Recent Choice",
1051
+ stats.get("most_recent_choice_timestamp", "N/A")
1052
+ )
1053
+
1054
+ console.print(table)
1055
+ console.print()
1056
+
1057
+ # Show templates used
1058
+ templates = stats.get("templates_used", [])
1059
+ if templates:
1060
+ console.print("[bold]Templates Used:[/bold]")
1061
+ for template_id in templates:
1062
+ console.print(f" • {template_id}")
1063
+ console.print()
1064
+
1065
+ except ImportError:
1066
+ console.print(
1067
+ "[red]Error:[/red] Session context not available. "
1068
+ "Ensure memory and session modules are installed."
1069
+ )
1070
+ raise typer.Exit(code=1)
1071
+ except Exception as e:
1072
+ console.print(f"[red]Error:[/red] {e}")
1073
+ raise typer.Exit(code=1)
1074
+
1075
+
1076
+ @meta_workflow_app.command("suggest-defaults")
1077
+ def suggest_defaults_cmd(
1078
+ template_id: str = typer.Argument(..., help="Template ID to get defaults for"),
1079
+ session_id: str | None = typer.Option(
1080
+ None,
1081
+ "--session-id",
1082
+ "-s",
1083
+ help="Session ID (optional)",
1084
+ ),
1085
+ user_id: str = typer.Option(
1086
+ "cli_user",
1087
+ "--user-id",
1088
+ "-u",
1089
+ help="User ID for session",
1090
+ ),
1091
+ ):
1092
+ """Get suggested default values based on session history.
1093
+
1094
+ Analyzes recent choices for the specified template and suggests
1095
+ intelligent defaults for the next run.
1096
+
1097
+ Examples:
1098
+ empathy meta-workflow suggest-defaults test_creation_management_workflow
1099
+ empathy meta-workflow suggest-defaults python_package_publish --session-id sess_123
1100
+ """
1101
+ try:
1102
+ from empathy_os.memory.unified import UnifiedMemory
1103
+ from empathy_os.meta_workflows.session_context import SessionContext
1104
+
1105
+ # Initialize
1106
+ memory = UnifiedMemory(user_id=user_id)
1107
+ session = SessionContext(memory=memory, session_id=session_id)
1108
+
1109
+ # Load template
1110
+ registry = TemplateRegistry()
1111
+ template = registry.load_template(template_id)
1112
+ if not template:
1113
+ console.print(f"[red]Error:[/red] Template not found: {template_id}")
1114
+ raise typer.Exit(code=1)
1115
+
1116
+ console.print(f"\n[bold]Suggested Defaults for:[/bold] {template.name}")
1117
+ console.print(f"[dim]Template ID: {template_id}[/dim]\n")
1118
+
1119
+ # Get suggestions
1120
+ defaults = session.suggest_defaults(
1121
+ template_id=template_id,
1122
+ form_schema=template.form_schema,
1123
+ )
1124
+
1125
+ if not defaults:
1126
+ console.print("[yellow]No suggestions available (no recent history).[/yellow]\n")
1127
+ return
1128
+
1129
+ # Display
1130
+ console.print(f"[green]Found {len(defaults)} suggested default(s):[/green]\n")
1131
+
1132
+ table = Table(show_header=True)
1133
+ table.add_column("Question ID", style="cyan")
1134
+ table.add_column("Suggested Value")
1135
+
1136
+ for question_id, value in defaults.items():
1137
+ # Find the question to get the display text
1138
+ question = next(
1139
+ (q for q in template.form_schema.questions if q.id == question_id),
1140
+ None
1141
+ )
1142
+ question_text = question.text if question else question_id
1143
+
1144
+ value_str = str(value)
1145
+ if isinstance(value, list):
1146
+ value_str = ", ".join(str(v) for v in value)
1147
+
1148
+ table.add_row(question_text, value_str)
1149
+
1150
+ console.print(table)
1151
+ console.print(
1152
+ f"\n[dim]Use these defaults by running:[/dim]\n"
1153
+ f" empathy meta-workflow run {template_id} --use-defaults\n"
1154
+ )
1155
+
1156
+ except ImportError:
1157
+ console.print(
1158
+ "[red]Error:[/red] Session context not available. "
1159
+ "Ensure memory and session modules are installed."
1160
+ )
1161
+ raise typer.Exit(code=1)
1162
+ except Exception as e:
1163
+ console.print(f"[red]Error:[/red] {e}")
1164
+ raise typer.Exit(code=1)
1165
+
1166
+
1167
+ # =============================================================================
1168
+ # Migration Commands
1169
+ # =============================================================================
1170
+
1171
+
1172
+ @meta_workflow_app.command("migrate")
1173
+ def show_migration_guide(
1174
+ crew_name: str | None = typer.Argument(
1175
+ None,
1176
+ help="Specific Crew workflow name (optional)",
1177
+ ),
1178
+ ):
1179
+ """Show migration guide from deprecated Crew workflows.
1180
+
1181
+ Displays information about migrating from the deprecated Crew-based
1182
+ workflows to the new meta-workflow system.
1183
+
1184
+ Examples:
1185
+ empathy meta-workflow migrate
1186
+ empathy meta-workflow migrate ReleasePreparationCrew
1187
+ """
1188
+ # Migration mapping
1189
+ CREW_MIGRATION_MAP = {
1190
+ "ReleasePreparationCrew": {
1191
+ "template_id": "release-prep",
1192
+ "old_import": "from empathy_os.workflows.release_prep_crew import ReleasePreparationCrew",
1193
+ "old_usage": "crew = ReleasePreparationCrew(project_root='.')\nresult = await crew.execute()",
1194
+ "new_usage": "empathy meta-workflow run release-prep",
1195
+ },
1196
+ "TestCoverageBoostCrew": {
1197
+ "template_id": "test-coverage-boost",
1198
+ "old_import": "from empathy_os.workflows.test_coverage_boost_crew import TestCoverageBoostCrew",
1199
+ "old_usage": "crew = TestCoverageBoostCrew(target_coverage=85.0)\nresult = await crew.execute()",
1200
+ "new_usage": "empathy meta-workflow run test-coverage-boost",
1201
+ },
1202
+ "TestMaintenanceCrew": {
1203
+ "template_id": "test-maintenance",
1204
+ "old_import": "from empathy_os.workflows.test_maintenance_crew import TestMaintenanceCrew",
1205
+ "old_usage": "crew = TestMaintenanceCrew('.')\nresult = await crew.run(mode='full')",
1206
+ "new_usage": "empathy meta-workflow run test-maintenance",
1207
+ },
1208
+ "ManageDocumentationCrew": {
1209
+ "template_id": "manage-docs",
1210
+ "old_import": "from empathy_os.workflows.manage_documentation import ManageDocumentationCrew",
1211
+ "old_usage": "crew = ManageDocumentationCrew()\nresult = await crew.execute(path='./src')",
1212
+ "new_usage": "empathy meta-workflow run manage-docs",
1213
+ },
1214
+ }
1215
+
1216
+ console.print("\n[bold cyan]🔄 Crew → Meta-Workflow Migration Guide[/bold cyan]\n")
1217
+
1218
+ if crew_name:
1219
+ # Show specific migration
1220
+ if crew_name not in CREW_MIGRATION_MAP:
1221
+ console.print(f"[red]Unknown Crew workflow:[/red] {crew_name}")
1222
+ console.print("\n[bold]Available Crew workflows:[/bold]")
1223
+ for name in CREW_MIGRATION_MAP:
1224
+ console.print(f" • {name}")
1225
+ raise typer.Exit(code=1)
1226
+
1227
+ info = CREW_MIGRATION_MAP[crew_name]
1228
+ console.print(f"[bold]Migrating:[/bold] {crew_name}\n")
1229
+
1230
+ console.print("[bold red]DEPRECATED (Before):[/bold red]")
1231
+ console.print(f"[dim]{info['old_import']}[/dim]")
1232
+ console.print(f"\n[yellow]{info['old_usage']}[/yellow]\n")
1233
+
1234
+ console.print("[bold green]RECOMMENDED (After):[/bold green]")
1235
+ console.print(f"[green]{info['new_usage']}[/green]\n")
1236
+
1237
+ console.print("[bold]Benefits:[/bold]")
1238
+ console.print(" ✓ No CrewAI/LangChain dependency required")
1239
+ console.print(" ✓ Interactive configuration via Socratic questions")
1240
+ console.print(" ✓ Automatic cost optimization with tier escalation")
1241
+ console.print(" ✓ Session context for learning preferences")
1242
+ console.print(" ✓ Built-in analytics and pattern learning\n")
1243
+
1244
+ console.print(f"[dim]Try it now: empathy meta-workflow run {info['template_id']}[/dim]\n")
1245
+
1246
+ else:
1247
+ # Show overview
1248
+ console.print("[bold]Why Migrate?[/bold]")
1249
+ console.print(" The Crew-based workflows are deprecated since v4.3.0.")
1250
+ console.print(" The meta-workflow system provides the same functionality")
1251
+ console.print(" with better cost optimization and no extra dependencies.\n")
1252
+
1253
+ # Show migration table
1254
+ table = Table(title="Migration Map", show_header=True)
1255
+ table.add_column("Deprecated Crew", style="yellow")
1256
+ table.add_column("Meta-Workflow Command", style="green")
1257
+ table.add_column("Template ID", style="cyan")
1258
+
1259
+ for crew_name, info in CREW_MIGRATION_MAP.items():
1260
+ table.add_row(
1261
+ crew_name,
1262
+ info["new_usage"],
1263
+ info["template_id"],
1264
+ )
1265
+
1266
+ console.print(table)
1267
+
1268
+ console.print("\n[bold]Quick Start:[/bold]")
1269
+ console.print(" 1. List available templates: [cyan]empathy meta-workflow list-templates[/cyan]")
1270
+ console.print(" 2. Run a workflow: [cyan]empathy meta-workflow run release-prep[/cyan]")
1271
+ console.print(" 3. View results: [cyan]empathy meta-workflow list-runs[/cyan]\n")
1272
+
1273
+ console.print("[bold]More Details:[/bold]")
1274
+ console.print(" • Migration guide: [dim]empathy meta-workflow migrate <CrewName>[/dim]")
1275
+ console.print(" • Full documentation: [dim]docs/CREWAI_MIGRATION.md[/dim]\n")
1276
+
1277
+
1278
+ # =============================================================================
1279
+ # Dynamic Agent/Team Creation Commands (v4.4)
1280
+ # =============================================================================
1281
+
1282
+
1283
+ @meta_workflow_app.command("create-agent")
1284
+ def create_agent(
1285
+ interactive: bool = typer.Option(
1286
+ True,
1287
+ "--interactive/--quick",
1288
+ "-i/-q",
1289
+ help="Use interactive Socratic-guided creation",
1290
+ ),
1291
+ name: str = typer.Option(
1292
+ None,
1293
+ "--name",
1294
+ "-n",
1295
+ help="Agent name (for quick mode)",
1296
+ ),
1297
+ role: str = typer.Option(
1298
+ None,
1299
+ "--role",
1300
+ "-r",
1301
+ help="Agent role description (for quick mode)",
1302
+ ),
1303
+ tier: str = typer.Option(
1304
+ "capable",
1305
+ "--tier",
1306
+ "-t",
1307
+ help="Model tier: cheap, capable, or premium",
1308
+ ),
1309
+ output_file: str = typer.Option(
1310
+ None,
1311
+ "--output",
1312
+ "-o",
1313
+ help="Save agent spec to file",
1314
+ ),
1315
+ ):
1316
+ """Create a custom AI agent with Socratic-guided questions.
1317
+
1318
+ Interactive mode asks clarifying questions to help you define:
1319
+ - Agent capabilities and responsibilities
1320
+ - Model tier selection (cost vs quality tradeoff)
1321
+ - Tools and success criteria
1322
+
1323
+ Quick mode creates an agent directly from provided options.
1324
+
1325
+ Examples:
1326
+ empathy meta-workflow create-agent --interactive
1327
+ empathy meta-workflow create-agent -q --name "SecurityBot" --role "Scan for vulnerabilities"
1328
+ """
1329
+ import json
1330
+
1331
+ if interactive:
1332
+ console.print("\n[bold cyan]🤖 Create Custom Agent - Socratic Guide[/bold cyan]\n")
1333
+ console.print("[dim]I'll ask you a few questions to help define your agent.[/dim]\n")
1334
+
1335
+ # Question 1: Purpose
1336
+ console.print("[bold]1. What should this agent do?[/bold]")
1337
+ purpose = typer.prompt(" Describe the agent's main purpose")
1338
+
1339
+ # Question 2: Specific tasks
1340
+ console.print("\n[bold]2. What specific tasks will it perform?[/bold]")
1341
+ console.print(" [dim]Examples: analyze code, generate tests, review PRs, write docs[/dim]")
1342
+ tasks = typer.prompt(" List main tasks (comma-separated)")
1343
+
1344
+ # Question 3: Tier selection
1345
+ console.print("\n[bold]3. What quality/cost balance do you need?[/bold]")
1346
+ console.print(" [dim]cheap[/dim] - Fast & low-cost, good for simple analysis")
1347
+ console.print(" [dim]capable[/dim] - Balanced, good for most development tasks")
1348
+ console.print(" [dim]premium[/dim] - Highest quality, for complex reasoning")
1349
+ tier = typer.prompt(" Select tier", default="capable")
1350
+
1351
+ # Question 4: Tools
1352
+ console.print("\n[bold]4. What tools should it have access to?[/bold]")
1353
+ console.print(" [dim]Examples: file_read, file_write, web_search, code_exec[/dim]")
1354
+ tools_input = typer.prompt(" List tools (comma-separated, or 'none')", default="none")
1355
+ tools = [t.strip() for t in tools_input.split(",")] if tools_input != "none" else []
1356
+
1357
+ # Question 5: Success criteria
1358
+ console.print("\n[bold]5. How will you measure success?[/bold]")
1359
+ success = typer.prompt(" Describe success criteria")
1360
+
1361
+ # Generate name from purpose
1362
+ name = purpose.split()[0].title() + "Agent" if not name else name
1363
+
1364
+ # Build agent spec
1365
+ agent_spec = {
1366
+ "name": name,
1367
+ "role": purpose,
1368
+ "tasks": [t.strip() for t in tasks.split(",")],
1369
+ "tier": tier,
1370
+ "tools": tools,
1371
+ "success_criteria": success,
1372
+ "base_template": "generic",
1373
+ }
1374
+
1375
+ else:
1376
+ # Quick mode
1377
+ if not name or not role:
1378
+ console.print("[red]Error:[/red] --name and --role required in quick mode")
1379
+ console.print("[dim]Use --interactive for guided creation[/dim]")
1380
+ raise typer.Exit(code=1)
1381
+
1382
+ agent_spec = {
1383
+ "name": name,
1384
+ "role": role,
1385
+ "tier": tier,
1386
+ "tools": [],
1387
+ "success_criteria": "Task completed successfully",
1388
+ "base_template": "generic",
1389
+ }
1390
+
1391
+ # Display result
1392
+ console.print("\n[bold green]✓ Agent Specification Created[/bold green]\n")
1393
+
1394
+ spec_json = json.dumps(agent_spec, indent=2)
1395
+ console.print(Panel(spec_json, title=f"Agent: {agent_spec['name']}", border_style="green"))
1396
+
1397
+ # Save if requested
1398
+ if output_file:
1399
+ Path(output_file).write_text(spec_json)
1400
+ console.print(f"\n[green]Saved to:[/green] {output_file}")
1401
+
1402
+ # Show usage
1403
+ console.print("\n[bold]Next Steps:[/bold]")
1404
+ console.print(" 1. Use this agent in a custom team: [cyan]empathy meta-workflow create-team[/cyan]")
1405
+ console.print(" 2. Or add to an existing template manually")
1406
+ console.print(f"\n[dim]Agent tier '{tier}' will cost approximately:")
1407
+ costs = {"cheap": "$0.001-0.01", "capable": "$0.01-0.05", "premium": "$0.05-0.20"}
1408
+ console.print(f" {costs.get(tier, costs['capable'])} per execution[/dim]\n")
1409
+
1410
+
1411
+ @meta_workflow_app.command("create-team")
1412
+ def create_team(
1413
+ interactive: bool = typer.Option(
1414
+ True,
1415
+ "--interactive/--quick",
1416
+ "-i/-q",
1417
+ help="Use interactive Socratic-guided creation",
1418
+ ),
1419
+ name: str = typer.Option(
1420
+ None,
1421
+ "--name",
1422
+ "-n",
1423
+ help="Team name (for quick mode)",
1424
+ ),
1425
+ goal: str = typer.Option(
1426
+ None,
1427
+ "--goal",
1428
+ "-g",
1429
+ help="Team goal description (for quick mode)",
1430
+ ),
1431
+ output_file: str = typer.Option(
1432
+ None,
1433
+ "--output",
1434
+ "-o",
1435
+ help="Save team template to file",
1436
+ ),
1437
+ ):
1438
+ """Create a custom AI agent team with Socratic-guided workflow.
1439
+
1440
+ Interactive mode asks clarifying questions to help you define:
1441
+ - Team composition and agent roles
1442
+ - Collaboration pattern (sequential, parallel, mixed)
1443
+ - Success criteria and cost estimates
1444
+
1445
+ Examples:
1446
+ empathy meta-workflow create-team --interactive
1447
+ empathy meta-workflow create-team -q --name "ReviewTeam" --goal "Code review pipeline"
1448
+ """
1449
+ import json
1450
+
1451
+ if interactive:
1452
+ console.print("\n[bold cyan]👥 Create Custom Agent Team - Socratic Guide[/bold cyan]\n")
1453
+ console.print("[dim]I'll help you design a team of agents that work together.[/dim]\n")
1454
+
1455
+ # Question 1: Goal
1456
+ console.print("[bold]1. What is the team's overall goal?[/bold]")
1457
+ console.print(" [dim]Example: prepare code for production release[/dim]")
1458
+ goal = typer.prompt(" Describe the team's mission")
1459
+
1460
+ # Question 2: Agent count
1461
+ console.print("\n[bold]2. How many agents should be on this team?[/bold]")
1462
+ console.print(" [dim]Typical teams have 2-5 agents with specialized roles[/dim]")
1463
+ agent_count = typer.prompt(" Number of agents", default="3")
1464
+ agent_count = int(agent_count)
1465
+
1466
+ # Question 3: Agent roles
1467
+ console.print(f"\n[bold]3. Define {agent_count} agent roles:[/bold]")
1468
+ console.print(" [dim]Common roles: analyst, reviewer, generator, validator, reporter[/dim]")
1469
+
1470
+ agents = []
1471
+ for i in range(agent_count):
1472
+ console.print(f"\n [bold]Agent {i+1}:[/bold]")
1473
+ role = typer.prompt(" Role name")
1474
+ purpose = typer.prompt(" What does this agent do?")
1475
+ tier = typer.prompt(" Tier (cheap/capable/premium)", default="capable")
1476
+
1477
+ agents.append({
1478
+ "role": role,
1479
+ "purpose": purpose,
1480
+ "tier": tier,
1481
+ "base_template": "generic",
1482
+ })
1483
+
1484
+ # Question 4: Collaboration pattern
1485
+ console.print("\n[bold]4. How should agents collaborate?[/bold]")
1486
+ console.print(" [dim]sequential[/dim] - Each agent waits for the previous one")
1487
+ console.print(" [dim]parallel[/dim] - All agents run simultaneously")
1488
+ console.print(" [dim]mixed[/dim] - Some parallel, then sequential synthesis")
1489
+ pattern = typer.prompt(" Collaboration pattern", default="sequential")
1490
+
1491
+ # Question 5: Team name
1492
+ console.print("\n[bold]5. What should we call this team?[/bold]")
1493
+ name = typer.prompt(" Team name", default=goal.split()[0].title() + "Team")
1494
+
1495
+ # Build team template
1496
+ team_template = {
1497
+ "id": name.lower().replace(" ", "-"),
1498
+ "name": name,
1499
+ "description": goal,
1500
+ "collaboration_pattern": pattern,
1501
+ "agents": agents,
1502
+ "estimated_cost_range": {
1503
+ "min": len(agents) * 0.01,
1504
+ "max": len(agents) * 0.15,
1505
+ },
1506
+ }
1507
+
1508
+ else:
1509
+ # Quick mode
1510
+ if not name or not goal:
1511
+ console.print("[red]Error:[/red] --name and --goal required in quick mode")
1512
+ console.print("[dim]Use --interactive for guided creation[/dim]")
1513
+ raise typer.Exit(code=1)
1514
+
1515
+ # Create a default 3-agent team
1516
+ team_template = {
1517
+ "id": name.lower().replace(" ", "-"),
1518
+ "name": name,
1519
+ "description": goal,
1520
+ "collaboration_pattern": "sequential",
1521
+ "agents": [
1522
+ {"role": "Analyst", "purpose": "Analyze requirements", "tier": "cheap", "base_template": "generic"},
1523
+ {"role": "Executor", "purpose": "Perform main task", "tier": "capable", "base_template": "generic"},
1524
+ {"role": "Validator", "purpose": "Verify results", "tier": "capable", "base_template": "generic"},
1525
+ ],
1526
+ "estimated_cost_range": {"min": 0.03, "max": 0.45},
1527
+ }
1528
+
1529
+ # Display result
1530
+ console.print("\n[bold green]✓ Agent Team Template Created[/bold green]\n")
1531
+
1532
+ spec_json = json.dumps(team_template, indent=2)
1533
+ console.print(Panel(spec_json, title=f"Team: {team_template['name']}", border_style="green"))
1534
+
1535
+ # Save if requested
1536
+ if output_file:
1537
+ Path(output_file).write_text(spec_json)
1538
+ console.print(f"\n[green]Saved to:[/green] {output_file}")
1539
+
1540
+ # Show usage
1541
+ console.print("\n[bold]Next Steps:[/bold]")
1542
+ console.print(f" 1. Save as template: [cyan]--output .empathy/meta_workflows/templates/{team_template['id']}.json[/cyan]")
1543
+ console.print(f" 2. Run the team: [cyan]empathy meta-workflow run {team_template['id']}[/cyan]")
1544
+
1545
+ cost_min = team_template['estimated_cost_range']['min']
1546
+ cost_max = team_template['estimated_cost_range']['max']
1547
+ console.print(f"\n[dim]Estimated cost: ${cost_min:.2f} - ${cost_max:.2f} per execution[/dim]\n")
1548
+
1549
+
1550
+ if __name__ == "__main__":
1551
+ meta_workflow_app()