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
@@ -1,422 +0,0 @@
1
- """Pattern Extraction Wizard
2
-
3
- Level 3 wizard that detects bug fixes in git diffs and suggests
4
- storing them as patterns for future reference.
5
-
6
- Copyright 2025 Smart AI Memory, LLC
7
- Licensed under Fair Source 0.9
8
- """
9
-
10
- import hashlib
11
- import json
12
- import logging
13
- import re
14
- import subprocess
15
- from datetime import datetime
16
- from pathlib import Path
17
- from typing import Any
18
-
19
- from .base_wizard import BaseWizard
20
-
21
- logger = logging.getLogger(__name__)
22
-
23
-
24
- class PatternExtractionWizard(BaseWizard):
25
- """Detects bug fixes and suggests pattern storage.
26
-
27
- Analyzes git diffs to identify:
28
- - Null checks added
29
- - Error handling added
30
- - Async/await fixes
31
- - Import fixes
32
- - Type fixes
33
-
34
- Suggests pre-filled patterns for easy storage.
35
- """
36
-
37
- @property
38
- def name(self) -> str:
39
- return "PatternExtractionWizard"
40
-
41
- @property
42
- def level(self) -> int:
43
- return 3 # Proactive
44
-
45
- def __init__(self, patterns_dir: str = "./patterns", **kwargs):
46
- super().__init__(**kwargs)
47
- self.patterns_dir = Path(patterns_dir)
48
-
49
- # Detection patterns for different fix types
50
- self._fix_patterns = {
51
- "null_reference": {
52
- "added": [
53
- r"\?\.", # Optional chaining
54
- r"\?\?\s*\[", # Nullish coalescing with array
55
- r"\?\?\s*\{", # Nullish coalescing with object
56
- r"if\s*\(\s*\w+\s*(!=|!==)\s*null", # Explicit null check
57
- r"\.get\s*\(", # Python .get() method
58
- r"getattr\s*\([^,]+,\s*[^,]+,\s*", # Python getattr with default
59
- r"or\s*\[\]", # Python or [] fallback
60
- r"or\s*\{\}", # Python or {} fallback
61
- ],
62
- "commit_keywords": ["null", "undefined", "none", "optional", "fallback"],
63
- "description": "Null/undefined reference fix",
64
- },
65
- "async_timing": {
66
- "added": [
67
- r"\bawait\s+", # Added await
68
- r"async\s+def\s+", # Made function async
69
- r"\.then\s*\(", # Added promise handling
70
- r"asyncio\.gather", # Added asyncio gather
71
- ],
72
- "commit_keywords": ["await", "async", "promise", "concurrent"],
73
- "description": "Async/timing fix",
74
- },
75
- "error_handling": {
76
- "added": [
77
- r"try\s*[:\{]", # Try block
78
- r"except\s+", # Python except
79
- r"catch\s*\(", # JS/TS catch
80
- r"\.catch\s*\(", # Promise catch
81
- r"finally\s*[:\{]", # Finally block
82
- r"raise\s+\w+Error", # Python raise
83
- r"throw\s+new\s+\w+Error", # JS throw
84
- ],
85
- "commit_keywords": ["error", "exception", "catch", "handle", "try"],
86
- "description": "Error handling improvement",
87
- },
88
- "type_mismatch": {
89
- "added": [
90
- r":\s*(str|int|float|bool|list|dict)\s*[=\)]", # Python type hints
91
- r":\s*(string|number|boolean|object)\s*[;=]", # TS types
92
- r"isinstance\s*\(", # Python isinstance
93
- r"typeof\s+\w+\s*===", # JS typeof check
94
- r"as\s+(str|int|float)", # Python cast
95
- ],
96
- "commit_keywords": ["type", "cast", "convert", "parse"],
97
- "description": "Type mismatch fix",
98
- },
99
- "import_error": {
100
- "added": [
101
- r"from\s+\w+\s+import", # Python import
102
- r"import\s+\w+\s+from", # ES6 import
103
- r"require\s*\(", # CommonJS require
104
- r"try:\s*\n\s*import", # Conditional import
105
- ],
106
- "commit_keywords": ["import", "module", "package", "dependency"],
107
- "description": "Import/dependency fix",
108
- },
109
- }
110
-
111
- async def analyze(self, context: dict[str, Any]) -> dict[str, Any]:
112
- """Analyze git diff for potential bug fix patterns.
113
-
114
- Args:
115
- context: {
116
- "diff": str - Git diff content (optional, will fetch if not provided)
117
- "commit_message": str - Commit message (optional)
118
- "commits": int - Number of recent commits to analyze (default 1)
119
- }
120
-
121
- Returns:
122
- {
123
- "suggested_patterns": list of suggested patterns,
124
- "predictions": list of predictions,
125
- "recommendations": list of recommendations,
126
- "confidence": float
127
- }
128
-
129
- """
130
- diff = context.get("diff")
131
- commit_message = context.get("commit_message", "")
132
- commits = context.get("commits", 1)
133
-
134
- # SECURITY: Validate commits parameter to prevent command injection
135
- # Must be a positive integer within reasonable bounds
136
- try:
137
- commits = int(commits)
138
- if commits < 1 or commits > 100:
139
- commits = 1
140
- except (TypeError, ValueError):
141
- commits = 1
142
-
143
- # Fetch diff if not provided
144
- if not diff:
145
- diff, commit_message = self._get_git_diff(commits)
146
-
147
- if not diff:
148
- return {
149
- "suggested_patterns": [],
150
- "predictions": [
151
- {
152
- "type": "no_changes",
153
- "severity": "info",
154
- "description": "No git changes detected to analyze.",
155
- },
156
- ],
157
- "recommendations": ["Make some code changes and try again."],
158
- "confidence": 0.0,
159
- }
160
-
161
- # Analyze the diff
162
- suggested_patterns = self._extract_patterns(diff, commit_message)
163
-
164
- # Generate predictions
165
- predictions = self._generate_predictions(suggested_patterns)
166
-
167
- # Generate recommendations
168
- recommendations = self._generate_recommendations(suggested_patterns)
169
-
170
- return {
171
- "suggested_patterns": suggested_patterns,
172
- "predictions": predictions,
173
- "recommendations": recommendations,
174
- "confidence": self._calculate_confidence(suggested_patterns),
175
- "metadata": {
176
- "wizard": self.name,
177
- "level": self.level,
178
- "timestamp": datetime.now().isoformat(),
179
- "diff_lines": len(diff.split("\n")),
180
- },
181
- }
182
-
183
- def _get_git_diff(self, commits: int = 1) -> tuple[str, str]:
184
- """Get git diff and commit message."""
185
- try:
186
- # Get diff
187
- diff_result = subprocess.run(
188
- ["git", "diff", f"HEAD~{commits}", "HEAD"],
189
- check=False,
190
- capture_output=True,
191
- text=True,
192
- timeout=10,
193
- )
194
- diff = diff_result.stdout if diff_result.returncode == 0 else ""
195
-
196
- # Get commit message
197
- msg_result = subprocess.run(
198
- ["git", "log", f"-{commits}", "--format=%s%n%b"],
199
- check=False,
200
- capture_output=True,
201
- text=True,
202
- timeout=5,
203
- )
204
- message = msg_result.stdout if msg_result.returncode == 0 else ""
205
-
206
- return diff, message
207
- except Exception as e:
208
- # Optional: Git operations unavailable (not a git repo or git not installed)
209
- logger.debug(f"Could not fetch git diff/message: {e}")
210
- return "", ""
211
-
212
- def _extract_patterns(self, diff: str, commit_message: str) -> list[dict]:
213
- """Extract potential bug fix patterns from diff."""
214
- suggested = []
215
- commit_lower = commit_message.lower()
216
-
217
- # Parse diff to get changed files and added lines
218
- current_file = ""
219
- added_lines: list[str] = []
220
-
221
- for line in diff.split("\n"):
222
- if line.startswith("diff --git"):
223
- # Save previous file's patterns
224
- if current_file and added_lines:
225
- file_patterns = self._analyze_file_changes(
226
- current_file,
227
- added_lines,
228
- commit_lower,
229
- )
230
- suggested.extend(file_patterns)
231
-
232
- # Start new file
233
- match = re.search(r"b/(.+)$", line)
234
- current_file = match.group(1) if match else ""
235
- added_lines = []
236
-
237
- elif line.startswith("+") and not line.startswith("+++"):
238
- added_lines.append(line[1:]) # Remove + prefix
239
-
240
- # Don't forget last file
241
- if current_file and added_lines:
242
- file_patterns = self._analyze_file_changes(current_file, added_lines, commit_lower)
243
- suggested.extend(file_patterns)
244
-
245
- return suggested
246
-
247
- def _analyze_file_changes(
248
- self,
249
- file_path: str,
250
- added_lines: list[str],
251
- commit_message: str,
252
- ) -> list[dict]:
253
- """Analyze changes to a single file for patterns."""
254
- patterns = []
255
- added_content = "\n".join(added_lines)
256
-
257
- for pattern_type, config in self._fix_patterns.items():
258
- # Check if any fix patterns were added
259
- matches = []
260
- for regex in config["added"]:
261
- found = re.findall(regex, added_content)
262
- if found:
263
- matches.extend(found)
264
-
265
- if not matches:
266
- continue
267
-
268
- # Check commit message for keywords
269
- keyword_match = any(kw in commit_message for kw in config["commit_keywords"])
270
-
271
- # Calculate confidence
272
- confidence = 0.5
273
- if keyword_match:
274
- confidence += 0.3
275
- if len(matches) > 1:
276
- confidence += 0.1
277
- confidence = min(confidence, 0.95)
278
-
279
- # Generate pattern suggestion
280
- pattern_id = self._generate_pattern_id(file_path, pattern_type)
281
-
282
- patterns.append(
283
- {
284
- "pattern_id": pattern_id,
285
- "type": pattern_type,
286
- "file": file_path,
287
- "matches": matches[:3], # Limit examples
288
- "confidence": confidence,
289
- "commit_keyword_match": keyword_match,
290
- "description": config["description"],
291
- "pre_filled": {
292
- "bug_id": pattern_id,
293
- "date": datetime.now().isoformat(),
294
- "file_path": file_path,
295
- "error_type": pattern_type,
296
- "error_message": f"Detected {str(config['description']).lower()}",
297
- "root_cause": "", # User fills in
298
- "fix_applied": config["description"],
299
- "fix_code": matches[0] if matches else "",
300
- "status": "investigating",
301
- },
302
- },
303
- )
304
-
305
- return patterns
306
-
307
- def _generate_pattern_id(self, file_path: str, pattern_type: str) -> str:
308
- """Generate a unique pattern ID."""
309
- date_str = datetime.now().strftime("%Y%m%d")
310
- content = f"{file_path}:{pattern_type}:{datetime.now().isoformat()}"
311
- hash_suffix = hashlib.md5(content.encode(), usedforsecurity=False).hexdigest()[:8]
312
- return f"bug_{date_str}_{hash_suffix}"
313
-
314
- def _generate_predictions(self, patterns: list[dict]) -> list[dict]:
315
- """Generate Level 3 predictions about patterns."""
316
- predictions: list[dict] = []
317
-
318
- if not patterns:
319
- return predictions
320
-
321
- # High confidence patterns
322
- high_conf = [p for p in patterns if p["confidence"] >= 0.8]
323
- if high_conf:
324
- predictions.append(
325
- {
326
- "type": "high_value_patterns",
327
- "severity": "info",
328
- "description": f"{len(high_conf)} high-confidence fix patterns detected. These are likely valuable for future reference.",
329
- },
330
- )
331
-
332
- # Common pattern types
333
- type_counts: dict[str, int] = {}
334
- for p in patterns:
335
- type_counts[p["type"]] = type_counts.get(p["type"], 0) + 1
336
-
337
- most_common = max(type_counts.items(), key=lambda x: x[1]) if type_counts else None
338
- if most_common and most_common[1] >= 2:
339
- predictions.append(
340
- {
341
- "type": "recurring_fix_type",
342
- "severity": "warning",
343
- "description": f"Multiple {most_common[0]} fixes detected ({most_common[1]}). Consider adding preventive checks.",
344
- },
345
- )
346
-
347
- return predictions
348
-
349
- def _generate_recommendations(self, patterns: list[dict]) -> list[str]:
350
- """Generate recommendations for pattern storage."""
351
- if not patterns:
352
- return ["No fix patterns detected in recent changes."]
353
-
354
- recommendations = []
355
-
356
- # Suggest storing high confidence patterns
357
- high_conf = [p for p in patterns if p["confidence"] >= 0.7]
358
- if high_conf:
359
- recommendations.append(
360
- f"Consider storing {len(high_conf)} detected fix pattern(s) for future reference.",
361
- )
362
-
363
- # Add specific storage command
364
- if patterns:
365
- first = patterns[0]
366
- recommendations.append(
367
- f"To store: empathy patterns resolve {first['pattern_id']} "
368
- f"--root-cause '<cause>' --fix '{first['description']}'",
369
- )
370
-
371
- return recommendations
372
-
373
- def _calculate_confidence(self, patterns: list[dict]) -> float:
374
- """Calculate overall confidence score."""
375
- if not patterns:
376
- return 0.0
377
-
378
- avg_conf = sum(p["confidence"] for p in patterns) / len(patterns)
379
- # Boost if multiple patterns detected
380
- if len(patterns) >= 2:
381
- avg_conf = min(avg_conf + 0.1, 1.0)
382
-
383
- return float(round(avg_conf, 2))
384
-
385
- async def save_pattern(self, pattern: dict) -> bool:
386
- """Save a suggested pattern to storage.
387
-
388
- Args:
389
- pattern: Pattern dict from suggested_patterns
390
-
391
- Returns:
392
- True if saved successfully
393
-
394
- """
395
- pre_filled = pattern.get("pre_filled", {})
396
- if not pre_filled:
397
- return False
398
-
399
- # Determine output directory
400
- output_dir = self.patterns_dir / "debugging"
401
- output_dir.mkdir(parents=True, exist_ok=True)
402
-
403
- # Write pattern file
404
- output_file = output_dir / f"{pre_filled['bug_id']}.json"
405
- try:
406
- with open(output_file, "w", encoding="utf-8") as f:
407
- json.dump(pre_filled, f, indent=2, default=str)
408
- return True
409
- except OSError:
410
- return False
411
-
412
-
413
- # CLI support
414
- if __name__ == "__main__":
415
- import asyncio
416
-
417
- async def main():
418
- wizard = PatternExtractionWizard()
419
- result = await wizard.analyze({"commits": 3})
420
- print(json.dumps(result, indent=2, default=str))
421
-
422
- asyncio.run(main())