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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/METADATA +7 -6
  2. empathy_framework-4.7.0.dist-info/RECORD +354 -0
  3. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/top_level.txt +0 -2
  4. empathy_healthcare_plugin/monitors/monitoring/__init__.py +9 -9
  5. empathy_llm_toolkit/agent_factory/__init__.py +6 -6
  6. empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +7 -10
  7. empathy_llm_toolkit/agents_md/__init__.py +22 -0
  8. empathy_llm_toolkit/agents_md/loader.py +218 -0
  9. empathy_llm_toolkit/agents_md/parser.py +271 -0
  10. empathy_llm_toolkit/agents_md/registry.py +307 -0
  11. empathy_llm_toolkit/commands/__init__.py +51 -0
  12. empathy_llm_toolkit/commands/context.py +375 -0
  13. empathy_llm_toolkit/commands/loader.py +301 -0
  14. empathy_llm_toolkit/commands/models.py +231 -0
  15. empathy_llm_toolkit/commands/parser.py +371 -0
  16. empathy_llm_toolkit/commands/registry.py +429 -0
  17. empathy_llm_toolkit/config/__init__.py +8 -8
  18. empathy_llm_toolkit/config/unified.py +3 -7
  19. empathy_llm_toolkit/context/__init__.py +22 -0
  20. empathy_llm_toolkit/context/compaction.py +455 -0
  21. empathy_llm_toolkit/context/manager.py +434 -0
  22. empathy_llm_toolkit/hooks/__init__.py +24 -0
  23. empathy_llm_toolkit/hooks/config.py +306 -0
  24. empathy_llm_toolkit/hooks/executor.py +289 -0
  25. empathy_llm_toolkit/hooks/registry.py +302 -0
  26. empathy_llm_toolkit/hooks/scripts/__init__.py +39 -0
  27. empathy_llm_toolkit/hooks/scripts/evaluate_session.py +201 -0
  28. empathy_llm_toolkit/hooks/scripts/first_time_init.py +285 -0
  29. empathy_llm_toolkit/hooks/scripts/pre_compact.py +207 -0
  30. empathy_llm_toolkit/hooks/scripts/session_end.py +183 -0
  31. empathy_llm_toolkit/hooks/scripts/session_start.py +163 -0
  32. empathy_llm_toolkit/hooks/scripts/suggest_compact.py +225 -0
  33. empathy_llm_toolkit/learning/__init__.py +30 -0
  34. empathy_llm_toolkit/learning/evaluator.py +438 -0
  35. empathy_llm_toolkit/learning/extractor.py +514 -0
  36. empathy_llm_toolkit/learning/storage.py +560 -0
  37. empathy_llm_toolkit/providers.py +4 -11
  38. empathy_llm_toolkit/security/__init__.py +17 -17
  39. empathy_llm_toolkit/utils/tokens.py +2 -5
  40. empathy_os/__init__.py +202 -70
  41. empathy_os/cache_monitor.py +5 -3
  42. empathy_os/cli/__init__.py +11 -55
  43. empathy_os/cli/__main__.py +29 -15
  44. empathy_os/cli/commands/inspection.py +21 -12
  45. empathy_os/cli/commands/memory.py +4 -12
  46. empathy_os/cli/commands/profiling.py +198 -0
  47. empathy_os/cli/commands/utilities.py +27 -7
  48. empathy_os/cli.py +28 -57
  49. empathy_os/cli_unified.py +525 -1164
  50. empathy_os/cost_tracker.py +9 -3
  51. empathy_os/dashboard/server.py +200 -2
  52. empathy_os/hot_reload/__init__.py +7 -7
  53. empathy_os/hot_reload/config.py +6 -7
  54. empathy_os/hot_reload/integration.py +35 -35
  55. empathy_os/hot_reload/reloader.py +57 -57
  56. empathy_os/hot_reload/watcher.py +28 -28
  57. empathy_os/hot_reload/websocket.py +2 -2
  58. empathy_os/memory/__init__.py +11 -4
  59. empathy_os/memory/claude_memory.py +1 -1
  60. empathy_os/memory/cross_session.py +8 -12
  61. empathy_os/memory/edges.py +6 -6
  62. empathy_os/memory/file_session.py +770 -0
  63. empathy_os/memory/graph.py +30 -30
  64. empathy_os/memory/nodes.py +6 -6
  65. empathy_os/memory/short_term.py +15 -9
  66. empathy_os/memory/unified.py +606 -140
  67. empathy_os/meta_workflows/agent_creator.py +3 -9
  68. empathy_os/meta_workflows/cli_meta_workflows.py +113 -53
  69. empathy_os/meta_workflows/form_engine.py +6 -18
  70. empathy_os/meta_workflows/intent_detector.py +64 -24
  71. empathy_os/meta_workflows/models.py +3 -1
  72. empathy_os/meta_workflows/pattern_learner.py +13 -31
  73. empathy_os/meta_workflows/plan_generator.py +55 -47
  74. empathy_os/meta_workflows/session_context.py +2 -3
  75. empathy_os/meta_workflows/workflow.py +20 -51
  76. empathy_os/models/cli.py +2 -2
  77. empathy_os/models/tasks.py +1 -2
  78. empathy_os/models/telemetry.py +4 -1
  79. empathy_os/models/token_estimator.py +3 -1
  80. empathy_os/monitoring/alerts.py +938 -9
  81. empathy_os/monitoring/alerts_cli.py +346 -183
  82. empathy_os/orchestration/execution_strategies.py +12 -29
  83. empathy_os/orchestration/pattern_learner.py +20 -26
  84. empathy_os/orchestration/real_tools.py +6 -15
  85. empathy_os/platform_utils.py +2 -1
  86. empathy_os/plugins/__init__.py +2 -2
  87. empathy_os/plugins/base.py +64 -64
  88. empathy_os/plugins/registry.py +32 -32
  89. empathy_os/project_index/index.py +49 -15
  90. empathy_os/project_index/models.py +1 -2
  91. empathy_os/project_index/reports.py +1 -1
  92. empathy_os/project_index/scanner.py +1 -0
  93. empathy_os/redis_memory.py +10 -7
  94. empathy_os/resilience/__init__.py +1 -1
  95. empathy_os/resilience/health.py +10 -10
  96. empathy_os/routing/__init__.py +7 -7
  97. empathy_os/routing/chain_executor.py +37 -37
  98. empathy_os/routing/classifier.py +36 -36
  99. empathy_os/routing/smart_router.py +40 -40
  100. empathy_os/routing/{wizard_registry.py → workflow_registry.py} +47 -47
  101. empathy_os/scaffolding/__init__.py +8 -8
  102. empathy_os/scaffolding/__main__.py +1 -1
  103. empathy_os/scaffolding/cli.py +28 -28
  104. empathy_os/socratic/__init__.py +3 -19
  105. empathy_os/socratic/ab_testing.py +25 -36
  106. empathy_os/socratic/blueprint.py +38 -38
  107. empathy_os/socratic/cli.py +34 -20
  108. empathy_os/socratic/collaboration.py +30 -28
  109. empathy_os/socratic/domain_templates.py +9 -1
  110. empathy_os/socratic/embeddings.py +17 -13
  111. empathy_os/socratic/engine.py +135 -70
  112. empathy_os/socratic/explainer.py +70 -60
  113. empathy_os/socratic/feedback.py +24 -19
  114. empathy_os/socratic/forms.py +15 -10
  115. empathy_os/socratic/generator.py +51 -35
  116. empathy_os/socratic/llm_analyzer.py +25 -23
  117. empathy_os/socratic/mcp_server.py +99 -159
  118. empathy_os/socratic/session.py +19 -13
  119. empathy_os/socratic/storage.py +98 -67
  120. empathy_os/socratic/success.py +38 -27
  121. empathy_os/socratic/visual_editor.py +51 -39
  122. empathy_os/socratic/web_ui.py +99 -66
  123. empathy_os/telemetry/cli.py +3 -1
  124. empathy_os/telemetry/usage_tracker.py +1 -3
  125. empathy_os/test_generator/__init__.py +3 -3
  126. empathy_os/test_generator/cli.py +28 -28
  127. empathy_os/test_generator/generator.py +64 -66
  128. empathy_os/test_generator/risk_analyzer.py +11 -11
  129. empathy_os/vscode_bridge.py +173 -0
  130. empathy_os/workflows/__init__.py +212 -120
  131. empathy_os/workflows/batch_processing.py +8 -24
  132. empathy_os/workflows/bug_predict.py +1 -1
  133. empathy_os/workflows/code_review.py +20 -5
  134. empathy_os/workflows/code_review_pipeline.py +13 -8
  135. empathy_os/workflows/keyboard_shortcuts/workflow.py +6 -2
  136. empathy_os/workflows/manage_documentation.py +1 -0
  137. empathy_os/workflows/orchestrated_health_check.py +6 -11
  138. empathy_os/workflows/orchestrated_release_prep.py +3 -3
  139. empathy_os/workflows/pr_review.py +18 -10
  140. empathy_os/workflows/progressive/__init__.py +2 -12
  141. empathy_os/workflows/progressive/cli.py +14 -37
  142. empathy_os/workflows/progressive/core.py +12 -12
  143. empathy_os/workflows/progressive/orchestrator.py +166 -144
  144. empathy_os/workflows/progressive/reports.py +22 -31
  145. empathy_os/workflows/progressive/telemetry.py +8 -14
  146. empathy_os/workflows/progressive/test_gen.py +29 -48
  147. empathy_os/workflows/progressive/workflow.py +31 -70
  148. empathy_os/workflows/release_prep.py +21 -6
  149. empathy_os/workflows/release_prep_crew.py +1 -0
  150. empathy_os/workflows/secure_release.py +13 -6
  151. empathy_os/workflows/security_audit.py +8 -3
  152. empathy_os/workflows/test_coverage_boost_crew.py +3 -2
  153. empathy_os/workflows/test_maintenance_crew.py +1 -0
  154. empathy_os/workflows/test_runner.py +16 -12
  155. empathy_software_plugin/SOFTWARE_PLUGIN_README.md +25 -703
  156. empathy_software_plugin/cli.py +0 -122
  157. coach_wizards/__init__.py +0 -45
  158. coach_wizards/accessibility_wizard.py +0 -91
  159. coach_wizards/api_wizard.py +0 -91
  160. coach_wizards/base_wizard.py +0 -209
  161. coach_wizards/cicd_wizard.py +0 -91
  162. coach_wizards/code_reviewer_README.md +0 -60
  163. coach_wizards/code_reviewer_wizard.py +0 -180
  164. coach_wizards/compliance_wizard.py +0 -91
  165. coach_wizards/database_wizard.py +0 -91
  166. coach_wizards/debugging_wizard.py +0 -91
  167. coach_wizards/documentation_wizard.py +0 -91
  168. coach_wizards/generate_wizards.py +0 -347
  169. coach_wizards/localization_wizard.py +0 -173
  170. coach_wizards/migration_wizard.py +0 -91
  171. coach_wizards/monitoring_wizard.py +0 -91
  172. coach_wizards/observability_wizard.py +0 -91
  173. coach_wizards/performance_wizard.py +0 -91
  174. coach_wizards/prompt_engineering_wizard.py +0 -661
  175. coach_wizards/refactoring_wizard.py +0 -91
  176. coach_wizards/scaling_wizard.py +0 -90
  177. coach_wizards/security_wizard.py +0 -92
  178. coach_wizards/testing_wizard.py +0 -91
  179. empathy_framework-4.6.6.dist-info/RECORD +0 -410
  180. empathy_llm_toolkit/wizards/__init__.py +0 -43
  181. empathy_llm_toolkit/wizards/base_wizard.py +0 -364
  182. empathy_llm_toolkit/wizards/customer_support_wizard.py +0 -190
  183. empathy_llm_toolkit/wizards/healthcare_wizard.py +0 -378
  184. empathy_llm_toolkit/wizards/patient_assessment_README.md +0 -64
  185. empathy_llm_toolkit/wizards/patient_assessment_wizard.py +0 -193
  186. empathy_llm_toolkit/wizards/technology_wizard.py +0 -209
  187. empathy_os/wizard_factory_cli.py +0 -170
  188. empathy_software_plugin/wizards/__init__.py +0 -42
  189. empathy_software_plugin/wizards/advanced_debugging_wizard.py +0 -395
  190. empathy_software_plugin/wizards/agent_orchestration_wizard.py +0 -511
  191. empathy_software_plugin/wizards/ai_collaboration_wizard.py +0 -503
  192. empathy_software_plugin/wizards/ai_context_wizard.py +0 -441
  193. empathy_software_plugin/wizards/ai_documentation_wizard.py +0 -503
  194. empathy_software_plugin/wizards/base_wizard.py +0 -288
  195. empathy_software_plugin/wizards/book_chapter_wizard.py +0 -519
  196. empathy_software_plugin/wizards/code_review_wizard.py +0 -604
  197. empathy_software_plugin/wizards/debugging/__init__.py +0 -50
  198. empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +0 -414
  199. empathy_software_plugin/wizards/debugging/config_loaders.py +0 -446
  200. empathy_software_plugin/wizards/debugging/fix_applier.py +0 -469
  201. empathy_software_plugin/wizards/debugging/language_patterns.py +0 -385
  202. empathy_software_plugin/wizards/debugging/linter_parsers.py +0 -470
  203. empathy_software_plugin/wizards/debugging/verification.py +0 -369
  204. empathy_software_plugin/wizards/enhanced_testing_wizard.py +0 -537
  205. empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +0 -816
  206. empathy_software_plugin/wizards/multi_model_wizard.py +0 -501
  207. empathy_software_plugin/wizards/pattern_extraction_wizard.py +0 -422
  208. empathy_software_plugin/wizards/pattern_retriever_wizard.py +0 -400
  209. empathy_software_plugin/wizards/performance/__init__.py +0 -9
  210. empathy_software_plugin/wizards/performance/bottleneck_detector.py +0 -221
  211. empathy_software_plugin/wizards/performance/profiler_parsers.py +0 -278
  212. empathy_software_plugin/wizards/performance/trajectory_analyzer.py +0 -429
  213. empathy_software_plugin/wizards/performance_profiling_wizard.py +0 -305
  214. empathy_software_plugin/wizards/prompt_engineering_wizard.py +0 -425
  215. empathy_software_plugin/wizards/rag_pattern_wizard.py +0 -461
  216. empathy_software_plugin/wizards/security/__init__.py +0 -32
  217. empathy_software_plugin/wizards/security/exploit_analyzer.py +0 -290
  218. empathy_software_plugin/wizards/security/owasp_patterns.py +0 -241
  219. empathy_software_plugin/wizards/security/vulnerability_scanner.py +0 -604
  220. empathy_software_plugin/wizards/security_analysis_wizard.py +0 -322
  221. empathy_software_plugin/wizards/security_learning_wizard.py +0 -740
  222. empathy_software_plugin/wizards/tech_debt_wizard.py +0 -726
  223. empathy_software_plugin/wizards/testing/__init__.py +0 -27
  224. empathy_software_plugin/wizards/testing/coverage_analyzer.py +0 -459
  225. empathy_software_plugin/wizards/testing/quality_analyzer.py +0 -525
  226. empathy_software_plugin/wizards/testing/test_suggester.py +0 -533
  227. empathy_software_plugin/wizards/testing_wizard.py +0 -274
  228. wizards/__init__.py +0 -82
  229. wizards/admission_assessment_wizard.py +0 -644
  230. wizards/care_plan.py +0 -321
  231. wizards/clinical_assessment.py +0 -769
  232. wizards/discharge_planning.py +0 -77
  233. wizards/discharge_summary_wizard.py +0 -468
  234. wizards/dosage_calculation.py +0 -497
  235. wizards/incident_report_wizard.py +0 -454
  236. wizards/medication_reconciliation.py +0 -85
  237. wizards/nursing_assessment.py +0 -171
  238. wizards/patient_education.py +0 -654
  239. wizards/quality_improvement.py +0 -705
  240. wizards/sbar_report.py +0 -324
  241. wizards/sbar_wizard.py +0 -608
  242. wizards/shift_handoff_wizard.py +0 -535
  243. wizards/soap_note_wizard.py +0 -679
  244. wizards/treatment_plan.py +0 -15
  245. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/WHEEL +0 -0
  246. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/entry_points.txt +0 -0
  247. {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -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())