empathy-framework 3.9.1__py3-none-any.whl → 3.9.2__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 (43) hide show
  1. {empathy_framework-3.9.1.dist-info → empathy_framework-3.9.2.dist-info}/METADATA +1 -1
  2. {empathy_framework-3.9.1.dist-info → empathy_framework-3.9.2.dist-info}/RECORD +40 -43
  3. empathy_healthcare_plugin/monitors/monitoring/__init__.py +9 -9
  4. empathy_llm_toolkit/agent_factory/__init__.py +6 -6
  5. empathy_llm_toolkit/agent_factory/adapters/crewai_adapter.py +4 -1
  6. empathy_llm_toolkit/agent_factory/framework.py +2 -1
  7. empathy_llm_toolkit/config/__init__.py +8 -8
  8. empathy_llm_toolkit/security/__init__.py +17 -17
  9. empathy_os/adaptive/__init__.py +3 -3
  10. empathy_os/cli.py +5 -8
  11. empathy_os/cli_unified.py +1 -1
  12. empathy_os/memory/__init__.py +30 -30
  13. empathy_os/memory/control_panel.py +3 -1
  14. empathy_os/memory/long_term.py +3 -1
  15. empathy_os/models/__init__.py +48 -48
  16. empathy_os/monitoring/__init__.py +7 -7
  17. empathy_os/optimization/__init__.py +3 -3
  18. empathy_os/pattern_library.py +2 -7
  19. empathy_os/plugins/__init__.py +6 -6
  20. empathy_os/resilience/__init__.py +5 -5
  21. empathy_os/scaffolding/cli.py +1 -1
  22. empathy_os/telemetry/cli.py +56 -13
  23. empathy_os/telemetry/usage_tracker.py +2 -5
  24. empathy_os/tier_recommender.py +36 -76
  25. empathy_os/trust/__init__.py +7 -7
  26. empathy_os/validation/__init__.py +3 -3
  27. empathy_os/workflow_patterns/output.py +1 -1
  28. empathy_os/workflow_patterns/structural.py +4 -4
  29. empathy_os/workflows/code_review_pipeline.py +1 -5
  30. empathy_os/workflows/dependency_check.py +1 -5
  31. empathy_os/workflows/keyboard_shortcuts/__init__.py +5 -5
  32. empathy_os/workflows/tier_tracking.py +39 -29
  33. empathy_software_plugin/cli.py +1 -3
  34. empathy_software_plugin/wizards/code_review_wizard.py +1 -3
  35. empathy_software_plugin/wizards/debugging/__init__.py +4 -4
  36. empathy_software_plugin/wizards/security/__init__.py +6 -6
  37. empathy_os/.empathy/costs.json +0 -60
  38. empathy_os/.empathy/discovery_stats.json +0 -15
  39. empathy_os/.empathy/workflow_runs.json +0 -45
  40. {empathy_framework-3.9.1.dist-info → empathy_framework-3.9.2.dist-info}/WHEEL +0 -0
  41. {empathy_framework-3.9.1.dist-info → empathy_framework-3.9.2.dist-info}/entry_points.txt +0 -0
  42. {empathy_framework-3.9.1.dist-info → empathy_framework-3.9.2.dist-info}/licenses/LICENSE +0 -0
  43. {empathy_framework-3.9.1.dist-info → empathy_framework-3.9.2.dist-info}/top_level.txt +0 -0
@@ -7,9 +7,9 @@ Licensed under Fair Source License 0.9
7
7
  """
8
8
 
9
9
  from empathy_os.validation.xml_validator import (
10
- ValidationResult,
11
- XMLValidator,
12
- validate_xml_response,
10
+ ValidationResult,
11
+ XMLValidator,
12
+ validate_xml_response,
13
13
  )
14
14
 
15
15
  __all__ = [
@@ -33,7 +33,7 @@ class ResultDataclassPattern(WorkflowPattern):
33
33
 
34
34
  def generate_code_sections(self, context: dict[str, Any]) -> list[CodeSection]:
35
35
  """Generate code for result dataclass."""
36
- workflow_name = context.get("workflow_name", "my-workflow")
36
+ context.get("workflow_name", "my-workflow")
37
37
  class_name = context.get("class_name", "MyWorkflow")
38
38
  result_class_name = f"{class_name}Result"
39
39
 
@@ -34,7 +34,7 @@ class SingleStagePattern(WorkflowPattern):
34
34
  def generate_code_sections(self, context: dict[str, Any]) -> list[CodeSection]:
35
35
  """Generate code for single-stage workflow."""
36
36
  workflow_name = context.get("workflow_name", "MyWorkflow")
37
- class_name = context.get("class_name", "MyWorkflow")
37
+ context.get("class_name", "MyWorkflow")
38
38
  description = context.get("description", "Single-stage workflow")
39
39
  tier = context.get("tier", "CAPABLE")
40
40
 
@@ -118,7 +118,7 @@ class MultiStagePattern(WorkflowPattern):
118
118
  def generate_code_sections(self, context: dict[str, Any]) -> list[CodeSection]:
119
119
  """Generate code for multi-stage workflow."""
120
120
  workflow_name = context.get("workflow_name", "my-workflow")
121
- class_name = context.get("class_name", "MyWorkflow")
121
+ context.get("class_name", "MyWorkflow")
122
122
  description = context.get("description", "Multi-stage workflow")
123
123
  stages = context.get("stages", ["analyze", "process", "report"])
124
124
  tier_map = context.get(
@@ -138,7 +138,7 @@ class MultiStagePattern(WorkflowPattern):
138
138
 
139
139
  # Generate stage routing
140
140
  stage_routing = []
141
- for i, stage in enumerate(stages):
141
+ for _i, stage in enumerate(stages):
142
142
  stage_routing.append(
143
143
  f""" if stage_name == "{stage}":
144
144
  return await self._{stage}(input_data, tier)"""
@@ -229,7 +229,7 @@ class CrewBasedPattern(WorkflowPattern):
229
229
  def generate_code_sections(self, context: dict[str, Any]) -> list[CodeSection]:
230
230
  """Generate code for crew-based workflow."""
231
231
  workflow_name = context.get("workflow_name", "my-crew-workflow")
232
- class_name = context.get("class_name", "MyCrewWorkflow")
232
+ context.get("class_name", "MyCrewWorkflow")
233
233
  description = context.get("description", "Crew-based workflow")
234
234
  crew_name = context.get("crew_name", "MyCrew")
235
235
 
@@ -605,11 +605,7 @@ def format_code_review_pipeline_report(result: CodeReviewPipelineResult) -> str:
605
605
  quality_label = (
606
606
  "EXCELLENT"
607
607
  if score >= 90
608
- else "GOOD"
609
- if score >= 70
610
- else "NEEDS WORK"
611
- if score >= 50
612
- else "POOR"
608
+ else "GOOD" if score >= 70 else "NEEDS WORK" if score >= 50 else "POOR"
613
609
  )
614
610
  lines.append("-" * 60)
615
611
  lines.append("QUALITY SCORE")
@@ -321,11 +321,7 @@ class DependencyCheckWorkflow(BaseWorkflow):
321
321
  risk_level = (
322
322
  "critical"
323
323
  if risk_score >= 75
324
- else "high"
325
- if risk_score >= 50
326
- else "medium"
327
- if risk_score >= 25
328
- else "low"
324
+ else "high" if risk_score >= 50 else "medium" if risk_score >= 25 else "low"
329
325
  )
330
326
 
331
327
  # Build vulnerability summary for LLM
@@ -12,11 +12,11 @@ Features:
12
12
 
13
13
  from .generators import CLIAliasGenerator, MarkdownDocGenerator, VSCodeKeybindingsGenerator
14
14
  from .parsers import (
15
- FeatureParser,
16
- LLMFeatureAnalyzer,
17
- PyProjectParser,
18
- VSCodeCommandParser,
19
- YAMLManifestParser,
15
+ FeatureParser,
16
+ LLMFeatureAnalyzer,
17
+ PyProjectParser,
18
+ VSCodeCommandParser,
19
+ YAMLManifestParser,
20
20
  )
21
21
  from .schema import Category, Feature, FeatureManifest, LayoutConfig, ShortcutAssignment
22
22
  from .workflow import KeyboardShortcutWorkflow
@@ -12,10 +12,10 @@ Licensed under Fair Source License 0.9
12
12
 
13
13
  import json
14
14
  import uuid
15
- from dataclasses import asdict, dataclass
15
+ from dataclasses import dataclass
16
16
  from datetime import datetime
17
17
  from pathlib import Path
18
- from typing import Any, Dict, List, Optional
18
+ from typing import Any
19
19
 
20
20
  from empathy_os.logging_config import get_logger
21
21
 
@@ -29,8 +29,8 @@ class TierAttempt:
29
29
  tier: str
30
30
  attempt: int
31
31
  success: bool
32
- quality_gate_failed: Optional[str] = None
33
- quality_gates_passed: Optional[List[str]] = None
32
+ quality_gate_failed: str | None = None
33
+ quality_gates_passed: list[str] | None = None
34
34
 
35
35
 
36
36
  @dataclass
@@ -40,7 +40,7 @@ class WorkflowTierProgression:
40
40
  workflow_name: str
41
41
  workflow_id: str
42
42
  bug_description: str
43
- files_affected: List[str]
43
+ files_affected: list[str]
44
44
  bug_type: str
45
45
 
46
46
  # Tier progression
@@ -48,7 +48,7 @@ class WorkflowTierProgression:
48
48
  starting_tier: str
49
49
  successful_tier: str
50
50
  total_attempts: int
51
- tier_history: List[Dict[str, Any]]
51
+ tier_history: list[dict[str, Any]]
52
52
 
53
53
  # Costs
54
54
  total_cost: float
@@ -65,7 +65,7 @@ class WorkflowTierProgression:
65
65
  duration_seconds: float
66
66
 
67
67
  # Optional fields must come last
68
- error_message: Optional[str] = None
68
+ error_message: str | None = None
69
69
 
70
70
 
71
71
  class WorkflowTierTracker:
@@ -89,7 +89,7 @@ class WorkflowTierTracker:
89
89
  self,
90
90
  workflow_name: str,
91
91
  workflow_description: str,
92
- patterns_dir: Optional[Path] = None,
92
+ patterns_dir: Path | None = None,
93
93
  ):
94
94
  """
95
95
  Initialize tier tracker for a workflow.
@@ -109,13 +109,13 @@ class WorkflowTierTracker:
109
109
  self.patterns_dir = Path(patterns_dir)
110
110
  self.patterns_dir.mkdir(parents=True, exist_ok=True)
111
111
 
112
- self.recommended_tier: Optional[str] = None
113
- self.starting_tier: Optional[str] = None
114
- self.tier_attempts: List[TierAttempt] = []
112
+ self.recommended_tier: str | None = None
113
+ self.starting_tier: str | None = None
114
+ self.tier_attempts: list[TierAttempt] = []
115
115
 
116
116
  def show_recommendation(
117
117
  self,
118
- files_affected: Optional[List[str]] = None,
118
+ files_affected: list[str] | None = None,
119
119
  show_ui: bool = True,
120
120
  ) -> str:
121
121
  """
@@ -173,7 +173,9 @@ class WorkflowTierTracker:
173
173
  if result.fallback_used:
174
174
  message += "\n\n[yellow]⚠️ Using default - limited historical data[/yellow]"
175
175
  else:
176
- message += f"\n\n[green]✅ Based on {result.similar_patterns_count} similar patterns[/green]"
176
+ message += (
177
+ f"\n\n[green]✅ Based on {result.similar_patterns_count} similar patterns[/green]"
178
+ )
177
179
 
178
180
  console.print(Panel(message, title="🎯 Auto Tier Recommendation", border_style="cyan"))
179
181
 
@@ -182,8 +184,8 @@ class WorkflowTierTracker:
182
184
  tier: str,
183
185
  attempt: int,
184
186
  success: bool,
185
- quality_gate_failed: Optional[str] = None,
186
- quality_gates_passed: Optional[List[str]] = None,
187
+ quality_gate_failed: str | None = None,
188
+ quality_gates_passed: list[str] | None = None,
187
189
  ):
188
190
  """Record a tier attempt during workflow execution."""
189
191
  self.tier_attempts.append(
@@ -199,9 +201,9 @@ class WorkflowTierTracker:
199
201
  def save_progression(
200
202
  self,
201
203
  workflow_result: Any,
202
- files_affected: Optional[List[str]] = None,
204
+ files_affected: list[str] | None = None,
203
205
  bug_type: str = "workflow_run",
204
- ) -> Optional[Path]:
206
+ ) -> Path | None:
205
207
  """
206
208
  Save tier progression data after workflow completion.
207
209
 
@@ -225,9 +227,17 @@ class WorkflowTierTracker:
225
227
  tier_history = self._build_tier_history(workflow_result)
226
228
 
227
229
  # Calculate costs
228
- total_cost = workflow_result.cost_report.get("total", 0) if isinstance(workflow_result.cost_report, dict) else sum(stage.cost for stage in workflow_result.stages)
230
+ total_cost = (
231
+ workflow_result.cost_report.get("total", 0)
232
+ if isinstance(workflow_result.cost_report, dict)
233
+ else sum(stage.cost for stage in workflow_result.stages)
234
+ )
229
235
  cost_if_premium = self._estimate_premium_cost(workflow_result)
230
- savings_percent = ((cost_if_premium - total_cost) / cost_if_premium * 100) if cost_if_premium > 0 else 0
236
+ savings_percent = (
237
+ ((cost_if_premium - total_cost) / cost_if_premium * 100)
238
+ if cost_if_premium > 0
239
+ else 0
240
+ )
231
241
 
232
242
  # Create progression record
233
243
  progression = {
@@ -240,7 +250,6 @@ class WorkflowTierTracker:
240
250
  "resolved_at": completed_at.strftime("%Y-%m-%d"),
241
251
  "files_affected": files_affected or [],
242
252
  "source": "workflow_tracking",
243
-
244
253
  "tier_progression": {
245
254
  "methodology": "AI-ADDIE",
246
255
  "recommended_tier": self.recommended_tier or self.starting_tier,
@@ -266,7 +275,6 @@ class WorkflowTierTracker:
266
275
  "false_complete_avoided": workflow_result.error is None,
267
276
  },
268
277
  },
269
-
270
278
  "workflow_metadata": {
271
279
  "workflow_name": self.workflow_name,
272
280
  "workflow_id": self.workflow_id,
@@ -298,8 +306,10 @@ class WorkflowTierTracker:
298
306
  return "CHEAP"
299
307
 
300
308
  # Use the highest tier that was actually used
301
- tiers_used = [stage.tier.value if hasattr(stage.tier, 'value') else str(stage.tier).lower()
302
- for stage in workflow_result.stages]
309
+ tiers_used = [
310
+ stage.tier.value if hasattr(stage.tier, "value") else str(stage.tier).lower()
311
+ for stage in workflow_result.stages
312
+ ]
303
313
 
304
314
  if "premium" in tiers_used:
305
315
  return "PREMIUM"
@@ -308,13 +318,13 @@ class WorkflowTierTracker:
308
318
  else:
309
319
  return "CHEAP"
310
320
 
311
- def _build_tier_history(self, workflow_result: Any) -> List[Dict[str, Any]]:
321
+ def _build_tier_history(self, workflow_result: Any) -> list[dict[str, Any]]:
312
322
  """Build tier history from workflow stages."""
313
- tier_groups: Dict[str, List[Any]] = {}
323
+ tier_groups: dict[str, list[Any]] = {}
314
324
 
315
325
  # Group stages by tier
316
326
  for stage in workflow_result.stages:
317
- tier = stage.tier.value if hasattr(stage.tier, 'value') else str(stage.tier).lower()
327
+ tier = stage.tier.value if hasattr(stage.tier, "value") else str(stage.tier).lower()
318
328
  tier_upper = tier.upper()
319
329
  if tier_upper not in tier_groups:
320
330
  tier_groups[tier_upper] = []
@@ -328,7 +338,7 @@ class WorkflowTierTracker:
328
338
  success_stage = None
329
339
 
330
340
  for i, stage in enumerate(stages, 1):
331
- if hasattr(stage, 'error') and stage.error:
341
+ if hasattr(stage, "error") and stage.error:
332
342
  failures.append({"attempt": i, "quality_gate_failed": "execution"})
333
343
  else:
334
344
  success_stage = i
@@ -364,7 +374,7 @@ class WorkflowTierTracker:
364
374
  # Rough estimate: PREMIUM tier is ~15x more expensive than CHEAP
365
375
  return actual_cost * 5 # Conservative multiplier
366
376
 
367
- def _update_consolidated_patterns(self, progression: Dict[str, Any]):
377
+ def _update_consolidated_patterns(self, progression: dict[str, Any]):
368
378
  """Update the consolidated patterns.json file."""
369
379
  consolidated_file = self.patterns_dir / "all_patterns.json"
370
380
 
@@ -391,7 +401,7 @@ class WorkflowTierTracker:
391
401
  def auto_recommend_tier(
392
402
  workflow_name: str,
393
403
  workflow_description: str,
394
- files_affected: Optional[List[str]] = None,
404
+ files_affected: list[str] | None = None,
395
405
  ) -> str:
396
406
  """
397
407
  Quick helper to get tier recommendation without tracker.
@@ -662,9 +662,7 @@ def scan_command():
662
662
  severity_icon = (
663
663
  "🔴"
664
664
  if issue.severity == "high"
665
- else "🟡"
666
- if issue.severity == "medium"
667
- else "🔵"
665
+ else "🟡" if issue.severity == "medium" else "🔵"
668
666
  )
669
667
  print(f" {severity_icon} Line {issue.line_number}: {issue.message}")
670
668
  if len(result.issues) > 3:
@@ -561,9 +561,7 @@ class CodeReviewWizard(BaseWizard):
561
561
  icon = (
562
562
  "⚠️"
563
563
  if finding["severity"] == "warning"
564
- else "❌"
565
- if finding["severity"] == "error"
566
- else "ℹ️"
564
+ else "❌" if finding["severity"] == "error" else "ℹ️"
567
565
  )
568
566
  lines.append(f"{icon} {finding['file']}:{finding['line']}")
569
567
  lines.append(f" Pattern: {finding['pattern_type']} ({finding['pattern_id']})")
@@ -10,10 +10,10 @@ from .bug_risk_analyzer import BugRisk, BugRiskAnalyzer, RiskAssessment
10
10
  from .config_loaders import ConfigLoaderFactory, LintConfig, load_config
11
11
  from .fix_applier import FixApplierFactory, FixResult, apply_fixes, group_issues_by_fixability
12
12
  from .language_patterns import (
13
- CrossLanguagePatternLibrary,
14
- PatternCategory,
15
- UniversalPattern,
16
- get_pattern_library,
13
+ CrossLanguagePatternLibrary,
14
+ PatternCategory,
15
+ UniversalPattern,
16
+ get_pattern_library,
17
17
  )
18
18
  from .linter_parsers import LinterParserFactory, LintIssue, Severity, parse_linter_output
19
19
  from .verification import VerificationResult, compare_issue_lists, run_linter, verify_fixes
@@ -9,12 +9,12 @@ Licensed under Fair Source License 0.9
9
9
  from .exploit_analyzer import ExploitAnalyzer
10
10
  from .owasp_patterns import OWASPPatternDetector
11
11
  from .vulnerability_scanner import (
12
- DependencyVulnerability,
13
- Severity,
14
- Vulnerability,
15
- VulnerabilityScanner,
16
- VulnerabilityScanReport,
17
- VulnerabilityType,
12
+ DependencyVulnerability,
13
+ Severity,
14
+ Vulnerability,
15
+ VulnerabilityScanner,
16
+ VulnerabilityScanReport,
17
+ VulnerabilityType,
18
18
  )
19
19
 
20
20
  __all__ = [
@@ -1,60 +0,0 @@
1
- {
2
- "requests": [
3
- {
4
- "timestamp": "2026-01-07T06:30:40.722211",
5
- "model": "claude-3-5-haiku-20241022",
6
- "tier": "cheap",
7
- "task_type": "workflow:refactor-plan:scan",
8
- "input_tokens": 0,
9
- "output_tokens": 572,
10
- "actual_cost": 0.002288,
11
- "baseline_cost": 0.0429,
12
- "savings": 0.040612
13
- },
14
- {
15
- "timestamp": "2026-01-07T06:30:40.723099",
16
- "model": "claude-sonnet-4-20250514",
17
- "tier": "capable",
18
- "task_type": "workflow:refactor-plan:analyze",
19
- "input_tokens": 676,
20
- "output_tokens": 193,
21
- "actual_cost": 0.004923,
22
- "baseline_cost": 0.024615,
23
- "savings": 0.019692
24
- },
25
- {
26
- "timestamp": "2026-01-07T06:30:43.930646",
27
- "model": "claude-sonnet-4-20250514",
28
- "tier": "capable",
29
- "task_type": "workflow:refactor-plan:prioritize",
30
- "input_tokens": 873,
31
- "output_tokens": 736,
32
- "actual_cost": 0.013659,
33
- "baseline_cost": 0.068295,
34
- "savings": 0.054636
35
- },
36
- {
37
- "timestamp": "2026-01-07T06:30:43.934470",
38
- "model": "claude-opus-4-5-20251101",
39
- "tier": "premium",
40
- "task_type": "workflow:refactor-plan:plan",
41
- "input_tokens": 0,
42
- "output_tokens": 0,
43
- "actual_cost": 0.0,
44
- "baseline_cost": 0.0,
45
- "savings": 0.0
46
- }
47
- ],
48
- "daily_totals": {
49
- "2026-01-07": {
50
- "requests": 4,
51
- "input_tokens": 1549,
52
- "output_tokens": 1501,
53
- "actual_cost": 0.02087,
54
- "baseline_cost": 0.13581,
55
- "savings": 0.11494
56
- }
57
- },
58
- "created_at": "2026-01-07T06:30:37.244775",
59
- "last_updated": "2026-01-07T06:30:43.934483"
60
- }
@@ -1,15 +0,0 @@
1
- {
2
- "command_counts": {
3
- "workflow": 1
4
- },
5
- "tips_shown": [
6
- "weekly_sync"
7
- ],
8
- "total_commands": 1,
9
- "patterns_learned": 0,
10
- "api_requests": 0,
11
- "tech_debt_trend": "unknown",
12
- "last_claude_sync": null,
13
- "first_run": "2026-01-07T06:30:43.936384",
14
- "last_updated": "2026-01-07T06:30:43.936546"
15
- }
@@ -1,45 +0,0 @@
1
- [
2
- {
3
- "workflow": "refactor-plan",
4
- "provider": "anthropic",
5
- "success": true,
6
- "started_at": "2026-01-07T06:30:40.702139",
7
- "completed_at": "2026-01-07T06:30:43.934850",
8
- "duration_ms": 3232,
9
- "cost": 0.02087,
10
- "baseline_cost": 0.13581,
11
- "savings": 0.11493999999999999,
12
- "savings_percent": 84.63294308224725,
13
- "stages": [
14
- {
15
- "name": "scan",
16
- "tier": "cheap",
17
- "skipped": false,
18
- "cost": 0.002288,
19
- "duration_ms": 20
20
- },
21
- {
22
- "name": "analyze",
23
- "tier": "capable",
24
- "skipped": false,
25
- "cost": 0.004923,
26
- "duration_ms": 0
27
- },
28
- {
29
- "name": "prioritize",
30
- "tier": "capable",
31
- "skipped": false,
32
- "cost": 0.013659,
33
- "duration_ms": 3207
34
- },
35
- {
36
- "name": "plan",
37
- "tier": "premium",
38
- "skipped": false,
39
- "cost": 0.0,
40
- "duration_ms": 3
41
- }
42
- ],
43
- "error": null
44
- }
45
- ]