empathy-framework 4.6.6__py3-none-any.whl → 4.7.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. empathy_framework-4.7.1.dist-info/METADATA +690 -0
  2. empathy_framework-4.7.1.dist-info/RECORD +379 -0
  3. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/top_level.txt +1 -2
  4. empathy_healthcare_plugin/monitors/monitoring/__init__.py +9 -9
  5. empathy_llm_toolkit/agent_factory/__init__.py +6 -6
  6. empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +7 -10
  7. empathy_llm_toolkit/agents_md/__init__.py +22 -0
  8. empathy_llm_toolkit/agents_md/loader.py +218 -0
  9. empathy_llm_toolkit/agents_md/parser.py +271 -0
  10. empathy_llm_toolkit/agents_md/registry.py +307 -0
  11. empathy_llm_toolkit/commands/__init__.py +51 -0
  12. empathy_llm_toolkit/commands/context.py +375 -0
  13. empathy_llm_toolkit/commands/loader.py +301 -0
  14. empathy_llm_toolkit/commands/models.py +231 -0
  15. empathy_llm_toolkit/commands/parser.py +371 -0
  16. empathy_llm_toolkit/commands/registry.py +429 -0
  17. empathy_llm_toolkit/config/__init__.py +8 -8
  18. empathy_llm_toolkit/config/unified.py +3 -7
  19. empathy_llm_toolkit/context/__init__.py +22 -0
  20. empathy_llm_toolkit/context/compaction.py +455 -0
  21. empathy_llm_toolkit/context/manager.py +434 -0
  22. empathy_llm_toolkit/hooks/__init__.py +24 -0
  23. empathy_llm_toolkit/hooks/config.py +306 -0
  24. empathy_llm_toolkit/hooks/executor.py +289 -0
  25. empathy_llm_toolkit/hooks/registry.py +302 -0
  26. empathy_llm_toolkit/hooks/scripts/__init__.py +39 -0
  27. empathy_llm_toolkit/hooks/scripts/evaluate_session.py +201 -0
  28. empathy_llm_toolkit/hooks/scripts/first_time_init.py +285 -0
  29. empathy_llm_toolkit/hooks/scripts/pre_compact.py +207 -0
  30. empathy_llm_toolkit/hooks/scripts/session_end.py +183 -0
  31. empathy_llm_toolkit/hooks/scripts/session_start.py +163 -0
  32. empathy_llm_toolkit/hooks/scripts/suggest_compact.py +225 -0
  33. empathy_llm_toolkit/learning/__init__.py +30 -0
  34. empathy_llm_toolkit/learning/evaluator.py +438 -0
  35. empathy_llm_toolkit/learning/extractor.py +514 -0
  36. empathy_llm_toolkit/learning/storage.py +560 -0
  37. empathy_llm_toolkit/providers.py +4 -11
  38. empathy_llm_toolkit/security/__init__.py +17 -17
  39. empathy_llm_toolkit/utils/tokens.py +2 -5
  40. empathy_os/__init__.py +202 -70
  41. empathy_os/cache_monitor.py +5 -3
  42. empathy_os/cli/__init__.py +11 -55
  43. empathy_os/cli/__main__.py +29 -15
  44. empathy_os/cli/commands/inspection.py +21 -12
  45. empathy_os/cli/commands/memory.py +4 -12
  46. empathy_os/cli/commands/profiling.py +198 -0
  47. empathy_os/cli/commands/utilities.py +27 -7
  48. empathy_os/cli.py +28 -57
  49. empathy_os/cli_unified.py +525 -1164
  50. empathy_os/cost_tracker.py +9 -3
  51. empathy_os/dashboard/server.py +200 -2
  52. empathy_os/hot_reload/__init__.py +7 -7
  53. empathy_os/hot_reload/config.py +6 -7
  54. empathy_os/hot_reload/integration.py +35 -35
  55. empathy_os/hot_reload/reloader.py +57 -57
  56. empathy_os/hot_reload/watcher.py +28 -28
  57. empathy_os/hot_reload/websocket.py +2 -2
  58. empathy_os/memory/__init__.py +11 -4
  59. empathy_os/memory/claude_memory.py +1 -1
  60. empathy_os/memory/cross_session.py +8 -12
  61. empathy_os/memory/edges.py +6 -6
  62. empathy_os/memory/file_session.py +770 -0
  63. empathy_os/memory/graph.py +30 -30
  64. empathy_os/memory/nodes.py +6 -6
  65. empathy_os/memory/short_term.py +15 -9
  66. empathy_os/memory/unified.py +606 -140
  67. empathy_os/meta_workflows/agent_creator.py +3 -9
  68. empathy_os/meta_workflows/cli_meta_workflows.py +113 -53
  69. empathy_os/meta_workflows/form_engine.py +6 -18
  70. empathy_os/meta_workflows/intent_detector.py +64 -24
  71. empathy_os/meta_workflows/models.py +3 -1
  72. empathy_os/meta_workflows/pattern_learner.py +13 -31
  73. empathy_os/meta_workflows/plan_generator.py +55 -47
  74. empathy_os/meta_workflows/session_context.py +2 -3
  75. empathy_os/meta_workflows/workflow.py +20 -51
  76. empathy_os/models/cli.py +2 -2
  77. empathy_os/models/tasks.py +1 -2
  78. empathy_os/models/telemetry.py +4 -1
  79. empathy_os/models/token_estimator.py +3 -1
  80. empathy_os/monitoring/alerts.py +938 -9
  81. empathy_os/monitoring/alerts_cli.py +346 -183
  82. empathy_os/orchestration/execution_strategies.py +12 -29
  83. empathy_os/orchestration/pattern_learner.py +20 -26
  84. empathy_os/orchestration/real_tools.py +6 -15
  85. empathy_os/platform_utils.py +2 -1
  86. empathy_os/plugins/__init__.py +2 -2
  87. empathy_os/plugins/base.py +64 -64
  88. empathy_os/plugins/registry.py +32 -32
  89. empathy_os/project_index/index.py +49 -15
  90. empathy_os/project_index/models.py +1 -2
  91. empathy_os/project_index/reports.py +1 -1
  92. empathy_os/project_index/scanner.py +1 -0
  93. empathy_os/redis_memory.py +10 -7
  94. empathy_os/resilience/__init__.py +1 -1
  95. empathy_os/resilience/health.py +10 -10
  96. empathy_os/routing/__init__.py +7 -7
  97. empathy_os/routing/chain_executor.py +37 -37
  98. empathy_os/routing/classifier.py +36 -36
  99. empathy_os/routing/smart_router.py +40 -40
  100. empathy_os/routing/{wizard_registry.py → workflow_registry.py} +47 -47
  101. empathy_os/scaffolding/__init__.py +8 -8
  102. empathy_os/scaffolding/__main__.py +1 -1
  103. empathy_os/scaffolding/cli.py +28 -28
  104. empathy_os/socratic/__init__.py +3 -19
  105. empathy_os/socratic/ab_testing.py +25 -36
  106. empathy_os/socratic/blueprint.py +38 -38
  107. empathy_os/socratic/cli.py +34 -20
  108. empathy_os/socratic/collaboration.py +30 -28
  109. empathy_os/socratic/domain_templates.py +9 -1
  110. empathy_os/socratic/embeddings.py +17 -13
  111. empathy_os/socratic/engine.py +135 -70
  112. empathy_os/socratic/explainer.py +70 -60
  113. empathy_os/socratic/feedback.py +24 -19
  114. empathy_os/socratic/forms.py +15 -10
  115. empathy_os/socratic/generator.py +51 -35
  116. empathy_os/socratic/llm_analyzer.py +25 -23
  117. empathy_os/socratic/mcp_server.py +99 -159
  118. empathy_os/socratic/session.py +19 -13
  119. empathy_os/socratic/storage.py +98 -67
  120. empathy_os/socratic/success.py +38 -27
  121. empathy_os/socratic/visual_editor.py +51 -39
  122. empathy_os/socratic/web_ui.py +99 -66
  123. empathy_os/telemetry/cli.py +3 -1
  124. empathy_os/telemetry/usage_tracker.py +1 -3
  125. empathy_os/test_generator/__init__.py +3 -3
  126. empathy_os/test_generator/cli.py +28 -28
  127. empathy_os/test_generator/generator.py +64 -66
  128. empathy_os/test_generator/risk_analyzer.py +11 -11
  129. empathy_os/vscode_bridge 2.py +173 -0
  130. empathy_os/vscode_bridge.py +173 -0
  131. empathy_os/workflows/__init__.py +212 -120
  132. empathy_os/workflows/batch_processing.py +8 -24
  133. empathy_os/workflows/bug_predict.py +1 -1
  134. empathy_os/workflows/code_review.py +20 -5
  135. empathy_os/workflows/code_review_pipeline.py +13 -8
  136. empathy_os/workflows/keyboard_shortcuts/workflow.py +6 -2
  137. empathy_os/workflows/manage_documentation.py +1 -0
  138. empathy_os/workflows/orchestrated_health_check.py +6 -11
  139. empathy_os/workflows/orchestrated_release_prep.py +3 -3
  140. empathy_os/workflows/pr_review.py +18 -10
  141. empathy_os/workflows/progressive/README 2.md +454 -0
  142. empathy_os/workflows/progressive/__init__ 2.py +92 -0
  143. empathy_os/workflows/progressive/__init__.py +2 -12
  144. empathy_os/workflows/progressive/cli 2.py +242 -0
  145. empathy_os/workflows/progressive/cli.py +14 -37
  146. empathy_os/workflows/progressive/core 2.py +488 -0
  147. empathy_os/workflows/progressive/core.py +12 -12
  148. empathy_os/workflows/progressive/orchestrator 2.py +701 -0
  149. empathy_os/workflows/progressive/orchestrator.py +166 -144
  150. empathy_os/workflows/progressive/reports 2.py +528 -0
  151. empathy_os/workflows/progressive/reports.py +22 -31
  152. empathy_os/workflows/progressive/telemetry 2.py +280 -0
  153. empathy_os/workflows/progressive/telemetry.py +8 -14
  154. empathy_os/workflows/progressive/test_gen 2.py +514 -0
  155. empathy_os/workflows/progressive/test_gen.py +29 -48
  156. empathy_os/workflows/progressive/workflow 2.py +628 -0
  157. empathy_os/workflows/progressive/workflow.py +31 -70
  158. empathy_os/workflows/release_prep.py +21 -6
  159. empathy_os/workflows/release_prep_crew.py +1 -0
  160. empathy_os/workflows/secure_release.py +13 -6
  161. empathy_os/workflows/security_audit.py +8 -3
  162. empathy_os/workflows/test_coverage_boost_crew.py +3 -2
  163. empathy_os/workflows/test_maintenance_crew.py +1 -0
  164. empathy_os/workflows/test_runner.py +16 -12
  165. empathy_software_plugin/SOFTWARE_PLUGIN_README.md +25 -703
  166. empathy_software_plugin/cli.py +0 -122
  167. patterns/README.md +119 -0
  168. patterns/__init__.py +95 -0
  169. patterns/behavior.py +298 -0
  170. patterns/code_review_memory.json +441 -0
  171. patterns/core.py +97 -0
  172. patterns/debugging.json +3763 -0
  173. patterns/empathy.py +268 -0
  174. patterns/health_check_memory.json +505 -0
  175. patterns/input.py +161 -0
  176. patterns/memory_graph.json +8 -0
  177. patterns/refactoring_memory.json +1113 -0
  178. patterns/registry.py +663 -0
  179. patterns/security_memory.json +8 -0
  180. patterns/structural.py +415 -0
  181. patterns/validation.py +194 -0
  182. coach_wizards/__init__.py +0 -45
  183. coach_wizards/accessibility_wizard.py +0 -91
  184. coach_wizards/api_wizard.py +0 -91
  185. coach_wizards/base_wizard.py +0 -209
  186. coach_wizards/cicd_wizard.py +0 -91
  187. coach_wizards/code_reviewer_README.md +0 -60
  188. coach_wizards/code_reviewer_wizard.py +0 -180
  189. coach_wizards/compliance_wizard.py +0 -91
  190. coach_wizards/database_wizard.py +0 -91
  191. coach_wizards/debugging_wizard.py +0 -91
  192. coach_wizards/documentation_wizard.py +0 -91
  193. coach_wizards/generate_wizards.py +0 -347
  194. coach_wizards/localization_wizard.py +0 -173
  195. coach_wizards/migration_wizard.py +0 -91
  196. coach_wizards/monitoring_wizard.py +0 -91
  197. coach_wizards/observability_wizard.py +0 -91
  198. coach_wizards/performance_wizard.py +0 -91
  199. coach_wizards/prompt_engineering_wizard.py +0 -661
  200. coach_wizards/refactoring_wizard.py +0 -91
  201. coach_wizards/scaling_wizard.py +0 -90
  202. coach_wizards/security_wizard.py +0 -92
  203. coach_wizards/testing_wizard.py +0 -91
  204. empathy_framework-4.6.6.dist-info/METADATA +0 -1597
  205. empathy_framework-4.6.6.dist-info/RECORD +0 -410
  206. empathy_llm_toolkit/wizards/__init__.py +0 -43
  207. empathy_llm_toolkit/wizards/base_wizard.py +0 -364
  208. empathy_llm_toolkit/wizards/customer_support_wizard.py +0 -190
  209. empathy_llm_toolkit/wizards/healthcare_wizard.py +0 -378
  210. empathy_llm_toolkit/wizards/patient_assessment_README.md +0 -64
  211. empathy_llm_toolkit/wizards/patient_assessment_wizard.py +0 -193
  212. empathy_llm_toolkit/wizards/technology_wizard.py +0 -209
  213. empathy_os/wizard_factory_cli.py +0 -170
  214. empathy_software_plugin/wizards/__init__.py +0 -42
  215. empathy_software_plugin/wizards/advanced_debugging_wizard.py +0 -395
  216. empathy_software_plugin/wizards/agent_orchestration_wizard.py +0 -511
  217. empathy_software_plugin/wizards/ai_collaboration_wizard.py +0 -503
  218. empathy_software_plugin/wizards/ai_context_wizard.py +0 -441
  219. empathy_software_plugin/wizards/ai_documentation_wizard.py +0 -503
  220. empathy_software_plugin/wizards/base_wizard.py +0 -288
  221. empathy_software_plugin/wizards/book_chapter_wizard.py +0 -519
  222. empathy_software_plugin/wizards/code_review_wizard.py +0 -604
  223. empathy_software_plugin/wizards/debugging/__init__.py +0 -50
  224. empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +0 -414
  225. empathy_software_plugin/wizards/debugging/config_loaders.py +0 -446
  226. empathy_software_plugin/wizards/debugging/fix_applier.py +0 -469
  227. empathy_software_plugin/wizards/debugging/language_patterns.py +0 -385
  228. empathy_software_plugin/wizards/debugging/linter_parsers.py +0 -470
  229. empathy_software_plugin/wizards/debugging/verification.py +0 -369
  230. empathy_software_plugin/wizards/enhanced_testing_wizard.py +0 -537
  231. empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +0 -816
  232. empathy_software_plugin/wizards/multi_model_wizard.py +0 -501
  233. empathy_software_plugin/wizards/pattern_extraction_wizard.py +0 -422
  234. empathy_software_plugin/wizards/pattern_retriever_wizard.py +0 -400
  235. empathy_software_plugin/wizards/performance/__init__.py +0 -9
  236. empathy_software_plugin/wizards/performance/bottleneck_detector.py +0 -221
  237. empathy_software_plugin/wizards/performance/profiler_parsers.py +0 -278
  238. empathy_software_plugin/wizards/performance/trajectory_analyzer.py +0 -429
  239. empathy_software_plugin/wizards/performance_profiling_wizard.py +0 -305
  240. empathy_software_plugin/wizards/prompt_engineering_wizard.py +0 -425
  241. empathy_software_plugin/wizards/rag_pattern_wizard.py +0 -461
  242. empathy_software_plugin/wizards/security/__init__.py +0 -32
  243. empathy_software_plugin/wizards/security/exploit_analyzer.py +0 -290
  244. empathy_software_plugin/wizards/security/owasp_patterns.py +0 -241
  245. empathy_software_plugin/wizards/security/vulnerability_scanner.py +0 -604
  246. empathy_software_plugin/wizards/security_analysis_wizard.py +0 -322
  247. empathy_software_plugin/wizards/security_learning_wizard.py +0 -740
  248. empathy_software_plugin/wizards/tech_debt_wizard.py +0 -726
  249. empathy_software_plugin/wizards/testing/__init__.py +0 -27
  250. empathy_software_plugin/wizards/testing/coverage_analyzer.py +0 -459
  251. empathy_software_plugin/wizards/testing/quality_analyzer.py +0 -525
  252. empathy_software_plugin/wizards/testing/test_suggester.py +0 -533
  253. empathy_software_plugin/wizards/testing_wizard.py +0 -274
  254. wizards/__init__.py +0 -82
  255. wizards/admission_assessment_wizard.py +0 -644
  256. wizards/care_plan.py +0 -321
  257. wizards/clinical_assessment.py +0 -769
  258. wizards/discharge_planning.py +0 -77
  259. wizards/discharge_summary_wizard.py +0 -468
  260. wizards/dosage_calculation.py +0 -497
  261. wizards/incident_report_wizard.py +0 -454
  262. wizards/medication_reconciliation.py +0 -85
  263. wizards/nursing_assessment.py +0 -171
  264. wizards/patient_education.py +0 -654
  265. wizards/quality_improvement.py +0 -705
  266. wizards/sbar_report.py +0 -324
  267. wizards/sbar_wizard.py +0 -608
  268. wizards/shift_handoff_wizard.py +0 -535
  269. wizards/soap_note_wizard.py +0 -679
  270. wizards/treatment_plan.py +0 -15
  271. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/WHEEL +0 -0
  272. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/entry_points.txt +0 -0
  273. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,280 @@
1
+ """Telemetry integration for progressive workflows.
2
+
3
+ Tracks cost, tier usage, escalation patterns, and savings for progressive workflows.
4
+ """
5
+
6
+ import logging
7
+ from datetime import datetime
8
+ from typing import Any
9
+
10
+ from empathy_os.telemetry.usage_tracker import UsageTracker
11
+ from empathy_os.workflows.progressive.core import (
12
+ ProgressiveWorkflowResult,
13
+ Tier,
14
+ TierResult,
15
+ )
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class ProgressiveTelemetry:
21
+ """Telemetry tracker for progressive workflows."""
22
+
23
+ def __init__(self, workflow_name: str, user_id: str | None = None) -> None:
24
+ """Initialize telemetry tracker.
25
+
26
+ Args:
27
+ workflow_name: Name of the workflow (e.g., "test-gen")
28
+ user_id: Optional user identifier (will be hashed)
29
+ """
30
+ self.workflow_name = workflow_name
31
+ self.user_id = user_id
32
+ self.tracker = UsageTracker.get_instance()
33
+
34
+ def track_tier_execution(
35
+ self,
36
+ tier_result: TierResult,
37
+ attempt: int,
38
+ escalated: bool,
39
+ escalation_reason: str | None = None,
40
+ ) -> None:
41
+ """Track a single tier execution.
42
+
43
+ Args:
44
+ tier_result: Result from tier execution
45
+ attempt: Attempt number for this tier
46
+ escalated: Whether this tier escalated to next
47
+ escalation_reason: Why escalation occurred (if escalated)
48
+ """
49
+ # Extract token counts from tier result
50
+ tokens = {
51
+ "input_tokens": tier_result.tokens_used.get("input", 0),
52
+ "output_tokens": tier_result.tokens_used.get("output", 0),
53
+ "total_tokens": tier_result.tokens_used.get("total", 0),
54
+ }
55
+
56
+ # Track LLM call
57
+ try:
58
+ self.tracker.track_llm_call(
59
+ workflow=self.workflow_name,
60
+ stage=f"tier-{tier_result.tier.value}-attempt-{attempt}",
61
+ tier=tier_result.tier.value.upper(),
62
+ model=tier_result.model,
63
+ provider=self._get_provider(tier_result.model),
64
+ cost=tier_result.cost,
65
+ tokens=tokens,
66
+ cache_hit=False, # Progressive workflows don't use cache
67
+ cache_type=None,
68
+ duration_ms=int(tier_result.duration * 1000),
69
+ user_id=self.user_id,
70
+ )
71
+
72
+ logger.debug(
73
+ f"Tracked {tier_result.tier.value} tier execution: "
74
+ f"${tier_result.cost:.3f}, {tokens['total_tokens']} tokens"
75
+ )
76
+
77
+ except Exception as e:
78
+ # Telemetry failure should not break workflow
79
+ logger.warning(f"Failed to track tier execution: {e}")
80
+
81
+ def track_workflow_completion(
82
+ self,
83
+ result: ProgressiveWorkflowResult,
84
+ ) -> None:
85
+ """Track complete workflow execution with cost savings analysis.
86
+
87
+ Args:
88
+ result: Final workflow result
89
+ """
90
+ try:
91
+ # Calculate metrics
92
+ total_items = len(result.final_result.generated_items)
93
+ total_cost = result.total_cost
94
+ total_duration_ms = int(result.total_duration * 1000)
95
+
96
+ # Cost savings vs all-premium
97
+ all_premium_cost = result._calculate_all_premium_cost()
98
+ savings = all_premium_cost - total_cost
99
+ savings_percent = (savings / all_premium_cost * 100) if all_premium_cost > 0 else 0
100
+
101
+ # Tier distribution
102
+ tier_breakdown = {}
103
+ for tier_result in result.tier_results:
104
+ tier_name = tier_result.tier.value
105
+ if tier_name not in tier_breakdown:
106
+ tier_breakdown[tier_name] = {
107
+ "items": 0,
108
+ "cost": 0.0,
109
+ "attempts": 0,
110
+ }
111
+ tier_breakdown[tier_name]["items"] += len(tier_result.generated_items)
112
+ tier_breakdown[tier_name]["cost"] += tier_result.cost
113
+ tier_breakdown[tier_name]["attempts"] += 1
114
+
115
+ # Log summary
116
+ logger.info(
117
+ f"Progressive workflow '{self.workflow_name}' completed:\n"
118
+ f" Items: {total_items}\n"
119
+ f" Cost: ${total_cost:.3f} (saved ${savings:.3f}, {savings_percent:.0f}%)\n"
120
+ f" Duration: {result.total_duration:.1f}s\n"
121
+ f" Tiers: {list(tier_breakdown.keys())}"
122
+ )
123
+
124
+ # Custom telemetry event for workflow summary
125
+ self._track_custom_event(
126
+ event_type="progressive_workflow_completion",
127
+ data={
128
+ "workflow": self.workflow_name,
129
+ "task_id": result.task_id,
130
+ "total_items": total_items,
131
+ "total_cost": total_cost,
132
+ "total_duration_ms": total_duration_ms,
133
+ "cost_savings": savings,
134
+ "savings_percent": savings_percent,
135
+ "all_premium_cost": all_premium_cost,
136
+ "tier_breakdown": tier_breakdown,
137
+ "success": result.success,
138
+ "final_cqs": result.final_result.failure_analysis.calculate_quality_score()
139
+ if result.final_result.failure_analysis
140
+ else None,
141
+ },
142
+ )
143
+
144
+ except Exception as e:
145
+ logger.warning(f"Failed to track workflow completion: {e}")
146
+
147
+ def track_escalation(
148
+ self,
149
+ from_tier: Tier,
150
+ to_tier: Tier,
151
+ reason: str,
152
+ item_count: int,
153
+ current_cost: float,
154
+ ) -> None:
155
+ """Track tier escalation event.
156
+
157
+ Args:
158
+ from_tier: Source tier
159
+ to_tier: Destination tier
160
+ reason: Why escalation occurred
161
+ item_count: Number of items being escalated
162
+ current_cost: Cost accumulated so far
163
+ """
164
+ try:
165
+ self._track_custom_event(
166
+ event_type="progressive_escalation",
167
+ data={
168
+ "workflow": self.workflow_name,
169
+ "from_tier": from_tier.value,
170
+ "to_tier": to_tier.value,
171
+ "reason": reason,
172
+ "item_count": item_count,
173
+ "current_cost": current_cost,
174
+ },
175
+ )
176
+
177
+ logger.info(
178
+ f"Escalated {item_count} items from {from_tier.value} → {to_tier.value}: {reason}"
179
+ )
180
+
181
+ except Exception as e:
182
+ logger.warning(f"Failed to track escalation: {e}")
183
+
184
+ def track_budget_exceeded(
185
+ self,
186
+ current_cost: float,
187
+ max_budget: float,
188
+ action: str,
189
+ ) -> None:
190
+ """Track budget exceeded event.
191
+
192
+ Args:
193
+ current_cost: Current cost that exceeded budget
194
+ max_budget: Maximum budget allowed
195
+ action: Action taken ("abort" or "warn")
196
+ """
197
+ try:
198
+ self._track_custom_event(
199
+ event_type="progressive_budget_exceeded",
200
+ data={
201
+ "workflow": self.workflow_name,
202
+ "current_cost": current_cost,
203
+ "max_budget": max_budget,
204
+ "overage": current_cost - max_budget,
205
+ "action": action,
206
+ },
207
+ )
208
+
209
+ logger.warning(
210
+ f"Budget exceeded: ${current_cost:.3f} > ${max_budget:.3f} ({action})"
211
+ )
212
+
213
+ except Exception as e:
214
+ logger.warning(f"Failed to track budget exceeded: {e}")
215
+
216
+ def _track_custom_event(self, event_type: str, data: dict[str, Any]) -> None:
217
+ """Track custom telemetry event.
218
+
219
+ Args:
220
+ event_type: Type of event
221
+ data: Event data
222
+ """
223
+ # For now, just log to telemetry directory as JSONL
224
+ # Future: could send to analytics service
225
+ import json
226
+ from pathlib import Path
227
+
228
+ try:
229
+ telemetry_dir = Path.home() / ".empathy" / "telemetry"
230
+ telemetry_dir.mkdir(parents=True, exist_ok=True)
231
+
232
+ events_file = telemetry_dir / "progressive_events.jsonl"
233
+
234
+ event = {
235
+ "timestamp": datetime.now().isoformat(),
236
+ "event_type": event_type,
237
+ "user_id_hash": (
238
+ self._hash_user_id(self.user_id) if self.user_id else "anonymous"
239
+ ),
240
+ **data,
241
+ }
242
+
243
+ with events_file.open("a") as f:
244
+ f.write(json.dumps(event) + "\n")
245
+
246
+ except Exception as e:
247
+ logger.debug(f"Failed to write custom event: {e}")
248
+
249
+ @staticmethod
250
+ def _get_provider(model: str) -> str:
251
+ """Infer provider from model name.
252
+
253
+ Args:
254
+ model: Model name
255
+
256
+ Returns:
257
+ Provider name
258
+ """
259
+ if "gpt" in model.lower():
260
+ return "openai"
261
+ elif "claude" in model.lower():
262
+ return "anthropic"
263
+ elif "gemini" in model.lower():
264
+ return "google"
265
+ else:
266
+ return "unknown"
267
+
268
+ @staticmethod
269
+ def _hash_user_id(user_id: str) -> str:
270
+ """Hash user ID for privacy.
271
+
272
+ Args:
273
+ user_id: User identifier
274
+
275
+ Returns:
276
+ SHA256 hash of user_id
277
+ """
278
+ import hashlib
279
+
280
+ return hashlib.sha256(user_id.encode()).hexdigest()
@@ -8,11 +8,7 @@ from datetime import datetime
8
8
  from typing import Any
9
9
 
10
10
  from empathy_os.telemetry.usage_tracker import UsageTracker
11
- from empathy_os.workflows.progressive.core import (
12
- ProgressiveWorkflowResult,
13
- Tier,
14
- TierResult,
15
- )
11
+ from empathy_os.workflows.progressive.core import ProgressiveWorkflowResult, Tier, TierResult
16
12
 
17
13
  logger = logging.getLogger(__name__)
18
14
 
@@ -135,9 +131,11 @@ class ProgressiveTelemetry:
135
131
  "all_premium_cost": all_premium_cost,
136
132
  "tier_breakdown": tier_breakdown,
137
133
  "success": result.success,
138
- "final_cqs": result.final_result.failure_analysis.calculate_quality_score()
139
- if result.final_result.failure_analysis
140
- else None,
134
+ "final_cqs": (
135
+ result.final_result.failure_analysis.calculate_quality_score()
136
+ if result.final_result.failure_analysis
137
+ else None
138
+ ),
141
139
  },
142
140
  )
143
141
 
@@ -206,9 +204,7 @@ class ProgressiveTelemetry:
206
204
  },
207
205
  )
208
206
 
209
- logger.warning(
210
- f"Budget exceeded: ${current_cost:.3f} > ${max_budget:.3f} ({action})"
211
- )
207
+ logger.warning(f"Budget exceeded: ${current_cost:.3f} > ${max_budget:.3f} ({action})")
212
208
 
213
209
  except Exception as e:
214
210
  logger.warning(f"Failed to track budget exceeded: {e}")
@@ -234,9 +230,7 @@ class ProgressiveTelemetry:
234
230
  event = {
235
231
  "timestamp": datetime.now().isoformat(),
236
232
  "event_type": event_type,
237
- "user_id_hash": (
238
- self._hash_user_id(self.user_id) if self.user_id else "anonymous"
239
- ),
233
+ "user_id_hash": (self._hash_user_id(self.user_id) if self.user_id else "anonymous"),
240
234
  **data,
241
235
  }
242
236