crackerjack 0.33.0__py3-none-any.whl → 0.33.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.

Potentially problematic release.


This version of crackerjack might be problematic. Click here for more details.

Files changed (198) hide show
  1. crackerjack/__main__.py +1350 -34
  2. crackerjack/adapters/__init__.py +17 -0
  3. crackerjack/adapters/lsp_client.py +358 -0
  4. crackerjack/adapters/rust_tool_adapter.py +194 -0
  5. crackerjack/adapters/rust_tool_manager.py +193 -0
  6. crackerjack/adapters/skylos_adapter.py +231 -0
  7. crackerjack/adapters/zuban_adapter.py +560 -0
  8. crackerjack/agents/base.py +7 -3
  9. crackerjack/agents/coordinator.py +271 -33
  10. crackerjack/agents/documentation_agent.py +9 -15
  11. crackerjack/agents/dry_agent.py +3 -15
  12. crackerjack/agents/formatting_agent.py +1 -1
  13. crackerjack/agents/import_optimization_agent.py +36 -180
  14. crackerjack/agents/performance_agent.py +17 -98
  15. crackerjack/agents/performance_helpers.py +7 -31
  16. crackerjack/agents/proactive_agent.py +1 -3
  17. crackerjack/agents/refactoring_agent.py +16 -85
  18. crackerjack/agents/refactoring_helpers.py +7 -42
  19. crackerjack/agents/security_agent.py +9 -48
  20. crackerjack/agents/test_creation_agent.py +356 -513
  21. crackerjack/agents/test_specialist_agent.py +0 -4
  22. crackerjack/api.py +6 -25
  23. crackerjack/cli/cache_handlers.py +204 -0
  24. crackerjack/cli/cache_handlers_enhanced.py +683 -0
  25. crackerjack/cli/facade.py +100 -0
  26. crackerjack/cli/handlers.py +224 -9
  27. crackerjack/cli/interactive.py +6 -4
  28. crackerjack/cli/options.py +642 -55
  29. crackerjack/cli/utils.py +2 -1
  30. crackerjack/code_cleaner.py +58 -117
  31. crackerjack/config/global_lock_config.py +8 -48
  32. crackerjack/config/hooks.py +53 -62
  33. crackerjack/core/async_workflow_orchestrator.py +24 -34
  34. crackerjack/core/autofix_coordinator.py +3 -17
  35. crackerjack/core/enhanced_container.py +4 -13
  36. crackerjack/core/file_lifecycle.py +12 -89
  37. crackerjack/core/performance.py +2 -2
  38. crackerjack/core/performance_monitor.py +15 -55
  39. crackerjack/core/phase_coordinator.py +104 -204
  40. crackerjack/core/resource_manager.py +14 -90
  41. crackerjack/core/service_watchdog.py +62 -95
  42. crackerjack/core/session_coordinator.py +149 -0
  43. crackerjack/core/timeout_manager.py +14 -72
  44. crackerjack/core/websocket_lifecycle.py +13 -78
  45. crackerjack/core/workflow_orchestrator.py +171 -174
  46. crackerjack/docs/INDEX.md +11 -0
  47. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  48. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  49. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  50. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  51. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  52. crackerjack/documentation/__init__.py +31 -0
  53. crackerjack/documentation/ai_templates.py +756 -0
  54. crackerjack/documentation/dual_output_generator.py +765 -0
  55. crackerjack/documentation/mkdocs_integration.py +518 -0
  56. crackerjack/documentation/reference_generator.py +977 -0
  57. crackerjack/dynamic_config.py +55 -50
  58. crackerjack/executors/async_hook_executor.py +10 -15
  59. crackerjack/executors/cached_hook_executor.py +117 -43
  60. crackerjack/executors/hook_executor.py +8 -34
  61. crackerjack/executors/hook_lock_manager.py +26 -183
  62. crackerjack/executors/individual_hook_executor.py +13 -11
  63. crackerjack/executors/lsp_aware_hook_executor.py +270 -0
  64. crackerjack/executors/tool_proxy.py +417 -0
  65. crackerjack/hooks/lsp_hook.py +79 -0
  66. crackerjack/intelligence/adaptive_learning.py +25 -10
  67. crackerjack/intelligence/agent_orchestrator.py +2 -5
  68. crackerjack/intelligence/agent_registry.py +34 -24
  69. crackerjack/intelligence/agent_selector.py +5 -7
  70. crackerjack/interactive.py +17 -6
  71. crackerjack/managers/async_hook_manager.py +0 -1
  72. crackerjack/managers/hook_manager.py +79 -1
  73. crackerjack/managers/publish_manager.py +44 -8
  74. crackerjack/managers/test_command_builder.py +1 -15
  75. crackerjack/managers/test_executor.py +1 -3
  76. crackerjack/managers/test_manager.py +98 -7
  77. crackerjack/managers/test_manager_backup.py +10 -9
  78. crackerjack/mcp/cache.py +2 -2
  79. crackerjack/mcp/client_runner.py +1 -1
  80. crackerjack/mcp/context.py +191 -68
  81. crackerjack/mcp/dashboard.py +7 -5
  82. crackerjack/mcp/enhanced_progress_monitor.py +31 -28
  83. crackerjack/mcp/file_monitor.py +30 -23
  84. crackerjack/mcp/progress_components.py +31 -21
  85. crackerjack/mcp/progress_monitor.py +50 -53
  86. crackerjack/mcp/rate_limiter.py +6 -6
  87. crackerjack/mcp/server_core.py +17 -16
  88. crackerjack/mcp/service_watchdog.py +2 -1
  89. crackerjack/mcp/state.py +4 -7
  90. crackerjack/mcp/task_manager.py +11 -9
  91. crackerjack/mcp/tools/core_tools.py +173 -32
  92. crackerjack/mcp/tools/error_analyzer.py +3 -2
  93. crackerjack/mcp/tools/execution_tools.py +8 -10
  94. crackerjack/mcp/tools/execution_tools_backup.py +42 -30
  95. crackerjack/mcp/tools/intelligence_tool_registry.py +7 -5
  96. crackerjack/mcp/tools/intelligence_tools.py +5 -2
  97. crackerjack/mcp/tools/monitoring_tools.py +33 -70
  98. crackerjack/mcp/tools/proactive_tools.py +24 -11
  99. crackerjack/mcp/tools/progress_tools.py +5 -8
  100. crackerjack/mcp/tools/utility_tools.py +20 -14
  101. crackerjack/mcp/tools/workflow_executor.py +62 -40
  102. crackerjack/mcp/websocket/app.py +8 -0
  103. crackerjack/mcp/websocket/endpoints.py +352 -357
  104. crackerjack/mcp/websocket/jobs.py +40 -57
  105. crackerjack/mcp/websocket/monitoring_endpoints.py +2935 -0
  106. crackerjack/mcp/websocket/server.py +7 -25
  107. crackerjack/mcp/websocket/websocket_handler.py +6 -17
  108. crackerjack/mixins/__init__.py +0 -2
  109. crackerjack/mixins/error_handling.py +1 -70
  110. crackerjack/models/config.py +12 -1
  111. crackerjack/models/config_adapter.py +49 -1
  112. crackerjack/models/protocols.py +122 -122
  113. crackerjack/models/resource_protocols.py +55 -210
  114. crackerjack/monitoring/ai_agent_watchdog.py +13 -13
  115. crackerjack/monitoring/metrics_collector.py +426 -0
  116. crackerjack/monitoring/regression_prevention.py +8 -8
  117. crackerjack/monitoring/websocket_server.py +643 -0
  118. crackerjack/orchestration/advanced_orchestrator.py +11 -6
  119. crackerjack/orchestration/coverage_improvement.py +3 -3
  120. crackerjack/orchestration/execution_strategies.py +26 -6
  121. crackerjack/orchestration/test_progress_streamer.py +8 -5
  122. crackerjack/plugins/base.py +2 -2
  123. crackerjack/plugins/hooks.py +7 -0
  124. crackerjack/plugins/managers.py +11 -8
  125. crackerjack/security/__init__.py +0 -1
  126. crackerjack/security/audit.py +6 -35
  127. crackerjack/services/anomaly_detector.py +392 -0
  128. crackerjack/services/api_extractor.py +615 -0
  129. crackerjack/services/backup_service.py +2 -2
  130. crackerjack/services/bounded_status_operations.py +15 -152
  131. crackerjack/services/cache.py +127 -1
  132. crackerjack/services/changelog_automation.py +395 -0
  133. crackerjack/services/config.py +15 -9
  134. crackerjack/services/config_merge.py +19 -80
  135. crackerjack/services/config_template.py +506 -0
  136. crackerjack/services/contextual_ai_assistant.py +48 -22
  137. crackerjack/services/coverage_badge_service.py +171 -0
  138. crackerjack/services/coverage_ratchet.py +27 -25
  139. crackerjack/services/debug.py +3 -3
  140. crackerjack/services/dependency_analyzer.py +460 -0
  141. crackerjack/services/dependency_monitor.py +14 -11
  142. crackerjack/services/documentation_generator.py +491 -0
  143. crackerjack/services/documentation_service.py +675 -0
  144. crackerjack/services/enhanced_filesystem.py +6 -5
  145. crackerjack/services/enterprise_optimizer.py +865 -0
  146. crackerjack/services/error_pattern_analyzer.py +676 -0
  147. crackerjack/services/file_hasher.py +1 -1
  148. crackerjack/services/git.py +8 -25
  149. crackerjack/services/health_metrics.py +10 -8
  150. crackerjack/services/heatmap_generator.py +735 -0
  151. crackerjack/services/initialization.py +11 -30
  152. crackerjack/services/input_validator.py +5 -97
  153. crackerjack/services/intelligent_commit.py +327 -0
  154. crackerjack/services/log_manager.py +15 -12
  155. crackerjack/services/logging.py +4 -3
  156. crackerjack/services/lsp_client.py +628 -0
  157. crackerjack/services/memory_optimizer.py +19 -87
  158. crackerjack/services/metrics.py +42 -33
  159. crackerjack/services/parallel_executor.py +9 -67
  160. crackerjack/services/pattern_cache.py +1 -1
  161. crackerjack/services/pattern_detector.py +6 -6
  162. crackerjack/services/performance_benchmarks.py +18 -59
  163. crackerjack/services/performance_cache.py +20 -81
  164. crackerjack/services/performance_monitor.py +27 -95
  165. crackerjack/services/predictive_analytics.py +510 -0
  166. crackerjack/services/quality_baseline.py +234 -0
  167. crackerjack/services/quality_baseline_enhanced.py +646 -0
  168. crackerjack/services/quality_intelligence.py +785 -0
  169. crackerjack/services/regex_patterns.py +605 -524
  170. crackerjack/services/regex_utils.py +43 -123
  171. crackerjack/services/secure_path_utils.py +5 -164
  172. crackerjack/services/secure_status_formatter.py +30 -141
  173. crackerjack/services/secure_subprocess.py +11 -92
  174. crackerjack/services/security.py +9 -41
  175. crackerjack/services/security_logger.py +12 -24
  176. crackerjack/services/server_manager.py +124 -16
  177. crackerjack/services/status_authentication.py +16 -159
  178. crackerjack/services/status_security_manager.py +4 -131
  179. crackerjack/services/thread_safe_status_collector.py +19 -125
  180. crackerjack/services/unified_config.py +21 -13
  181. crackerjack/services/validation_rate_limiter.py +5 -54
  182. crackerjack/services/version_analyzer.py +459 -0
  183. crackerjack/services/version_checker.py +1 -1
  184. crackerjack/services/websocket_resource_limiter.py +10 -144
  185. crackerjack/services/zuban_lsp_service.py +390 -0
  186. crackerjack/slash_commands/__init__.py +2 -7
  187. crackerjack/slash_commands/run.md +2 -2
  188. crackerjack/tools/validate_input_validator_patterns.py +14 -40
  189. crackerjack/tools/validate_regex_patterns.py +19 -48
  190. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/METADATA +196 -25
  191. crackerjack-0.33.1.dist-info/RECORD +229 -0
  192. crackerjack/CLAUDE.md +0 -207
  193. crackerjack/RULES.md +0 -380
  194. crackerjack/py313.py +0 -234
  195. crackerjack-0.33.0.dist-info/RECORD +0 -187
  196. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/WHEEL +0 -0
  197. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/entry_points.txt +0 -0
  198. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/licenses/LICENSE +0 -0
@@ -64,29 +64,24 @@ class PhaseCoordinator(ErrorHandlingMixin):
64
64
  security_logger=None,
65
65
  backup_service=None,
66
66
  )
67
- # Initialize configuration service - could be injected via DI
67
+
68
68
  from crackerjack.services.config import ConfigurationService
69
69
 
70
70
  self.config_service = ConfigurationService(console=console, pkg_path=pkg_path)
71
- # Lazy-loaded autofix coordinator (now using lazy service)
72
- # self.autofix_coordinator will be accessed via property
73
71
 
74
72
  self.logger = logging.getLogger("crackerjack.phases")
75
73
 
76
- # Performance optimization services
77
74
  self._memory_optimizer = get_memory_optimizer()
78
75
  self._parallel_executor = get_parallel_executor()
79
76
  self._async_executor = get_async_executor()
80
77
  self._git_cache = get_git_cache()
81
78
  self._filesystem_cache = get_filesystem_cache()
82
79
 
83
- # Lazy-loaded heavy services
84
80
  self._lazy_autofix = create_lazy_service(
85
81
  lambda: AutofixCoordinator(console=console, pkg_path=pkg_path),
86
82
  "autofix_coordinator",
87
83
  )
88
84
 
89
- # Initialize ErrorHandlingMixin
90
85
  super().__init__()
91
86
 
92
87
  def run_cleaning_phase(self, options: OptionsProtocol) -> bool:
@@ -110,17 +105,42 @@ class PhaseCoordinator(ErrorHandlingMixin):
110
105
  self.console.print("-" * 40 + "\n")
111
106
  self.console.print("[yellow]🧹[/yellow] Starting code cleaning...")
112
107
 
108
+ def _display_version_bump_header(self, version_type: str) -> None:
109
+ self.console.print("\n" + "-" * 74)
110
+ self.console.print(
111
+ f"[bold bright_magenta]📦 BUMP VERSION[/bold bright_magenta] [bold bright_white]Updating package version ({version_type})[/bold bright_white]",
112
+ )
113
+ self.console.print("-" * 74 + "\n")
114
+
115
+ def _display_publish_header(self) -> None:
116
+ self.console.print("\n" + "-" * 74)
117
+ self.console.print(
118
+ "[bold bright_yellow]🚀 PUBLISH[/bold bright_yellow] [bold bright_white]Publishing to PyPI[/bold bright_white]",
119
+ )
120
+ self.console.print("-" * 74 + "\n")
121
+
122
+ def _display_git_staging_header(self) -> None:
123
+ self.console.print("\n" + "-" * 74)
124
+ self.console.print(
125
+ "[bold bright_cyan]🏷️ GIT OPERATIONS[/bold bright_cyan] [bold bright_white]Staging files and creating tags[/bold bright_white]",
126
+ )
127
+ self.console.print("-" * 74 + "\n")
128
+
129
+ def _display_commit_push_header(self) -> None:
130
+ self.console.print("\n" + "-" * 74)
131
+ self.console.print(
132
+ "[bold bright_green]📤 COMMIT & PUSH[/bold bright_green] [bold bright_white]Committing and pushing changes[/bold bright_white]",
133
+ )
134
+ self.console.print("-" * 74 + "\n")
135
+
113
136
  def _execute_cleaning_process(self) -> bool:
114
- # Use the comprehensive backup cleaning system for safety
115
137
  cleaning_result = self.code_cleaner.clean_files(self.pkg_path, use_backup=True)
116
138
 
117
139
  if isinstance(cleaning_result, list):
118
- # Legacy mode (should not happen with use_backup=True, but handle gracefully)
119
140
  cleaned_files = [str(r.file_path) for r in cleaning_result if r.success]
120
141
  self._report_cleaning_results(cleaned_files)
121
142
  return all(r.success for r in cleaning_result) if cleaning_result else True
122
143
  else:
123
- # PackageCleaningResult from backup mode
124
144
  self._report_package_cleaning_results(cleaning_result)
125
145
  return cleaning_result.overall_success
126
146
 
@@ -141,7 +161,6 @@ class PhaseCoordinator(ErrorHandlingMixin):
141
161
  self.session.complete_task("cleaning", "No cleaning needed")
142
162
 
143
163
  def _report_package_cleaning_results(self, result: PackageCleaningResult) -> None:
144
- """Report package cleaning results with backup information."""
145
164
  if result.overall_success:
146
165
  self.console.print(
147
166
  f"[green]✅[/ green] Package cleaning completed successfully! "
@@ -188,31 +207,13 @@ class PhaseCoordinator(ErrorHandlingMixin):
188
207
  return False
189
208
 
190
209
  def _execute_configuration_steps(self, options: OptionsProtocol) -> bool:
191
- """Execute all configuration steps and return overall success."""
192
210
  success = True
193
211
 
194
- # FIRST STEP: Smart config merge before all other operations
195
- self._handle_smart_config_merge(options)
196
-
197
- # Handle crackerjack project specific configuration
198
- if self._is_crackerjack_project() and not self._copy_config_files_to_package():
199
- success = False
200
-
201
- # Update configuration files
202
212
  success &= self._update_configuration_files(options)
203
213
 
204
214
  return success
205
215
 
206
- def _handle_smart_config_merge(self, options: OptionsProtocol) -> None:
207
- """Handle smart config merge with warning on failure."""
208
- if not self._perform_smart_config_merge(options):
209
- self.console.print(
210
- "[yellow]⚠️[/yellow] Smart config merge encountered issues (continuing)"
211
- )
212
- # Don't fail the entire configuration phase, just log the warning
213
-
214
216
  def _update_configuration_files(self, options: OptionsProtocol) -> bool:
215
- """Update precommit and pyproject configuration files."""
216
217
  success = True
217
218
  if not self.config_service.update_precommit_config(options):
218
219
  success = False
@@ -221,7 +222,6 @@ class PhaseCoordinator(ErrorHandlingMixin):
221
222
  return success
222
223
 
223
224
  def _complete_configuration_task(self, success: bool) -> None:
224
- """Complete the configuration task with appropriate message."""
225
225
  message = (
226
226
  "Configuration updated successfully"
227
227
  if success
@@ -229,95 +229,6 @@ class PhaseCoordinator(ErrorHandlingMixin):
229
229
  )
230
230
  self.session.complete_task("configuration", message)
231
231
 
232
- def _perform_smart_config_merge(self, options: OptionsProtocol) -> bool:
233
- """Perform smart config merge before git operations."""
234
- try:
235
- self.logger.debug("Starting smart config merge process")
236
-
237
- # Smart merge for critical configuration files
238
- merged_files = []
239
-
240
- # Skip smart merge if explicitly requested or in specific modes
241
- if hasattr(options, "skip_config_merge") and options.skip_config_merge:
242
- self.logger.debug("Config merge skipped by option")
243
- return True
244
-
245
- # Merge .gitignore patterns (always safe to do)
246
- if self._smart_merge_gitignore():
247
- merged_files.append(".gitignore")
248
-
249
- # Merge configuration files (pyproject.toml, .pre-commit-config.yaml)
250
- # Only for crackerjack projects to avoid breaking user projects
251
- if self._is_crackerjack_project():
252
- if self._smart_merge_project_configs():
253
- merged_files.extend(["pyproject.toml", ".pre-commit-config.yaml"])
254
-
255
- if merged_files:
256
- files_str = ", ".join(merged_files)
257
- self.console.print(
258
- f"[green]🔧[/green] Smart-merged configurations: {files_str}"
259
- )
260
- self.logger.info(f"Smart config merge completed: {merged_files}")
261
- else:
262
- self.logger.debug("No configuration files needed smart merging")
263
-
264
- return True
265
-
266
- except Exception as e:
267
- self.console.print(f"[yellow]⚠️[/yellow] Smart config merge failed: {e}")
268
- self.logger.warning(
269
- f"Smart config merge failed: {e} (type: {type(e).__name__})"
270
- )
271
- # Return True to not block the workflow - this is fail-safe
272
- return True
273
-
274
- def _smart_merge_gitignore(self) -> bool:
275
- """Smart merge .gitignore patterns."""
276
- try:
277
- gitignore_path = self.pkg_path / ".gitignore"
278
- if not gitignore_path.exists():
279
- return False
280
-
281
- # Standard crackerjack ignore patterns to merge
282
- standard_patterns = [
283
- "# Crackerjack generated files",
284
- ".crackerjack/",
285
- "*.crackerjack.bak",
286
- ".coverage.*",
287
- "crackerjack-debug-*.log",
288
- "__pycache__/",
289
- "*.py[cod]",
290
- "*$py.class",
291
- ".pytest_cache/",
292
- ".tox/",
293
- ".mypy_cache/",
294
- ".ruff_cache/",
295
- ]
296
-
297
- self.config_merge_service.smart_merge_gitignore(
298
- patterns=standard_patterns, target_path=str(gitignore_path)
299
- )
300
-
301
- return True
302
-
303
- except Exception as e:
304
- self.logger.warning(f"Failed to smart merge .gitignore: {e}")
305
- return False
306
-
307
- def _smart_merge_project_configs(self) -> bool:
308
- """Smart merge pyproject.toml and pre-commit config for crackerjack projects."""
309
- try:
310
- # This would be where we implement project config merging
311
- # For now, just return True as the existing config service handles this
312
- self.logger.debug(
313
- "Project config smart merge placeholder - handled by existing config service"
314
- )
315
- return True
316
-
317
- except Exception as e:
318
- self.logger.warning(f"Failed to smart merge project configs: {e}")
319
- return False
320
-
321
232
  def _is_crackerjack_project(self) -> bool:
322
233
  pyproject_path = self.pkg_path / "pyproject.toml"
323
234
  if not pyproject_path.exists():
@@ -329,58 +240,11 @@ class PhaseCoordinator(ErrorHandlingMixin):
329
240
  with pyproject_path.open("rb") as f:
330
241
  data = tomllib.load(f)
331
242
 
332
- project_name = data.get("project", {}).get("name", "")
243
+ project_name: str = data.get("project", {}).get("name", "")
333
244
  return project_name == "crackerjack"
334
245
  except Exception:
335
246
  return False
336
247
 
337
- def _copy_config_files_to_package(self) -> bool:
338
- try:
339
- files_to_copy = [
340
- "pyproject.toml",
341
- ".pre-commit-config.yaml",
342
- "CLAUDE.md",
343
- "RULES.md",
344
- ".gitignore",
345
- "example.mcp.json",
346
- "uv.lock",
347
- ]
348
-
349
- package_dir = self.pkg_path / "crackerjack"
350
- if not package_dir.exists():
351
- self.console.print(
352
- "[yellow]⚠️[/ yellow] Package directory not found: crackerjack /",
353
- )
354
- return False
355
-
356
- copied_count = 0
357
- for filename in files_to_copy:
358
- src_path = self.pkg_path / filename
359
- if src_path.exists():
360
- dst_path = package_dir / filename
361
- try:
362
- import shutil
363
-
364
- shutil.copy2(src_path, dst_path)
365
- copied_count += 1
366
- self.logger.debug(f"Copied {filename} to package directory")
367
- except Exception as e:
368
- self.console.print(
369
- f"[yellow]⚠️[/ yellow] Failed to copy {filename}: {e}",
370
- )
371
-
372
- if copied_count > 0:
373
- self.console.print(
374
- f"[green]✅[/ green] Copied {copied_count} config files to package directory",
375
- )
376
-
377
- return True
378
- except Exception as e:
379
- self.console.print(
380
- f"[red]❌[/ red] Failed to copy config files to package: {e}",
381
- )
382
- return False
383
-
384
248
  def run_hooks_phase(self, options: OptionsProtocol) -> bool:
385
249
  if options.skip_hooks:
386
250
  return True
@@ -398,7 +262,6 @@ class PhaseCoordinator(ErrorHandlingMixin):
398
262
  if options.skip_hooks:
399
263
  return True
400
264
 
401
- # Use standard execution for now - parallel support can be added later
402
265
  hook_results = self.hook_manager.run_fast_hooks()
403
266
  return all(r.status == "passed" for r in hook_results)
404
267
 
@@ -406,7 +269,6 @@ class PhaseCoordinator(ErrorHandlingMixin):
406
269
  if options.skip_hooks:
407
270
  return True
408
271
 
409
- # Use standard execution for now - parallel support can be added later
410
272
  hook_results = self.hook_manager.run_comprehensive_hooks()
411
273
  return all(r.status == "passed" for r in hook_results)
412
274
 
@@ -415,11 +277,11 @@ class PhaseCoordinator(ErrorHandlingMixin):
415
277
  return True
416
278
  self.session.track_task("testing", "Test execution")
417
279
  try:
418
- self.console.print("\n" + "-" * 40)
280
+ self.console.print("\n" + "-" * 74)
419
281
  self.console.print(
420
282
  "[bold bright_blue]🧪 TESTS[/ bold bright_blue] [bold bright_white]Running test suite[/ bold bright_white]",
421
283
  )
422
- self.console.print("-" * 40 + "\n")
284
+ self.console.print("-" * 74 + "\n")
423
285
  if not self.test_manager.validate_test_environment():
424
286
  self.session.fail_task("testing", "Test environment validation failed")
425
287
  return False
@@ -454,9 +316,15 @@ class PhaseCoordinator(ErrorHandlingMixin):
454
316
 
455
317
  def _determine_version_type(self, options: OptionsProtocol) -> str | None:
456
318
  if options.publish:
457
- return options.publish
319
+ publish_value: str | None = (
320
+ options.publish if isinstance(options.publish, str) else None
321
+ )
322
+ return publish_value
458
323
  if options.all:
459
- return options.all
324
+ all_value: str | None = (
325
+ options.all if isinstance(options.all, str) else None
326
+ )
327
+ return all_value
460
328
  if options.bump:
461
329
  self._handle_version_bump_only(options.bump)
462
330
  return None
@@ -467,9 +335,12 @@ class PhaseCoordinator(ErrorHandlingMixin):
467
335
  options: OptionsProtocol,
468
336
  version_type: str,
469
337
  ) -> bool:
338
+ # Display version bump header
339
+ self._display_version_bump_header(version_type)
470
340
  new_version = self.publish_manager.bump_version(version_type)
471
341
 
472
- # Stage all changes after version bumping and code cleaning (if enabled)
342
+ # Display git operations header for staging and tagging
343
+ self._display_git_staging_header()
473
344
  self.console.print("[blue]📂[/ blue] Staging all changes for publishing...")
474
345
  if not self.git_service.add_all_files():
475
346
  self.console.print(
@@ -479,6 +350,8 @@ class PhaseCoordinator(ErrorHandlingMixin):
479
350
  if not options.no_git_tags:
480
351
  self.publish_manager.create_git_tag(new_version)
481
352
 
353
+ # Display publish header
354
+ self._display_publish_header()
482
355
  if self.publish_manager.publish_package():
483
356
  self._handle_successful_publish(options, new_version)
484
357
  return True
@@ -500,6 +373,9 @@ class PhaseCoordinator(ErrorHandlingMixin):
500
373
  def run_commit_phase(self, options: OptionsProtocol) -> bool:
501
374
  if not options.commit:
502
375
  return True
376
+
377
+ # Display commit & push header
378
+ self._display_commit_push_header()
503
379
  self.session.track_task("commit", "Git commit and push")
504
380
  try:
505
381
  changed_files = self.git_service.get_changed_files()
@@ -515,7 +391,6 @@ class PhaseCoordinator(ErrorHandlingMixin):
515
391
  def _handle_no_changes_to_commit(self) -> bool:
516
392
  self.console.print("[yellow]ℹ️[/ yellow] No changes to commit")
517
393
 
518
- # Check if there are unpushed commits
519
394
  from contextlib import suppress
520
395
 
521
396
  with suppress(ValueError, Exception):
@@ -583,6 +458,8 @@ class PhaseCoordinator(ErrorHandlingMixin):
583
458
  def _handle_version_bump_only(self, bump_type: str) -> bool:
584
459
  self.session.track_task("version_bump", f"Version bump ({bump_type})")
585
460
  try:
461
+ # Display version bump header
462
+ self._display_version_bump_header(bump_type)
586
463
  new_version = self.publish_manager.bump_version(bump_type)
587
464
  self.console.print(f"[green]🎯[/ green] Version bumped to {new_version}")
588
465
  self.session.complete_task("version_bump", f"Bumped to {new_version}")
@@ -597,6 +474,49 @@ class PhaseCoordinator(ErrorHandlingMixin):
597
474
  changed_files: list[str],
598
475
  options: OptionsProtocol,
599
476
  ) -> str:
477
+ # Check if smart commit is enabled
478
+ if getattr(options, "smart_commit", False):
479
+ try:
480
+ from crackerjack.services.intelligent_commit import (
481
+ CommitMessageGenerator,
482
+ )
483
+
484
+ self.console.print(
485
+ "[cyan]🤖[/cyan] Generating intelligent commit message..."
486
+ )
487
+ commit_generator = CommitMessageGenerator(
488
+ console=self.console, git_service=self.git_service
489
+ )
490
+
491
+ intelligent_message = commit_generator.generate_commit_message(
492
+ include_body=False,
493
+ conventional_commits=True,
494
+ )
495
+
496
+ if not options.interactive:
497
+ self.console.print(
498
+ f"[green]✨[/green] Generated: {intelligent_message}"
499
+ )
500
+ return intelligent_message
501
+
502
+ # In interactive mode, offer the intelligent message plus fallback suggestions
503
+ suggestions = [intelligent_message]
504
+ fallback_suggestions = self.git_service.get_commit_message_suggestions(
505
+ changed_files
506
+ )
507
+ suggestions.extend(
508
+ fallback_suggestions[:3]
509
+ ) # Add up to 3 fallback options
510
+
511
+ return self._interactive_commit_message_selection(suggestions)
512
+
513
+ except Exception as e:
514
+ self.console.print(
515
+ f"[yellow]⚠️[/yellow] Intelligent commit generation failed: {e}"
516
+ )
517
+ # Fallback to original logic
518
+
519
+ # Original logic for non-smart commits
600
520
  suggestions = self.git_service.get_commit_message_suggestions(changed_files)
601
521
 
602
522
  if not suggestions:
@@ -663,7 +583,6 @@ class PhaseCoordinator(ErrorHandlingMixin):
663
583
  def _execute_single_hook_attempt(
664
584
  self, hook_runner: t.Callable[[], list[t.Any]]
665
585
  ) -> tuple[list[t.Any], dict[str, t.Any]] | None:
666
- """Execute a single hook attempt and return results and summary."""
667
586
  try:
668
587
  results = hook_runner()
669
588
  summary = self.hook_manager.get_hook_summary(results)
@@ -680,7 +599,6 @@ class PhaseCoordinator(ErrorHandlingMixin):
680
599
  attempt: int,
681
600
  max_retries: int,
682
601
  ) -> str:
683
- """Process hook results and return action: 'continue', 'success', or 'failure'."""
684
602
  if not self._has_hook_failures(summary):
685
603
  self._handle_hook_success(hook_type, summary)
686
604
  return "success"
@@ -722,12 +640,12 @@ class PhaseCoordinator(ErrorHandlingMixin):
722
640
  return False
723
641
 
724
642
  def _attempt_autofix_for_fast_hooks(self, results: list[t.Any]) -> bool:
725
- """Attempt to autofix fast hook failures using lazy-loaded coordinator."""
726
643
  try:
727
644
  self.logger.info("Attempting autofix for fast hook failures")
728
- # Apply autofixes for fast hooks using lazy-loaded service
645
+
729
646
  autofix_coordinator = self._lazy_autofix.get()
730
- return autofix_coordinator.apply_fast_stage_fixes()
647
+ fix_result: bool = autofix_coordinator.apply_fast_stage_fixes()
648
+ return fix_result
731
649
  except Exception as e:
732
650
  self.logger.warning(f"Autofix attempt failed: {e}")
733
651
  return False
@@ -749,15 +667,13 @@ class PhaseCoordinator(ErrorHandlingMixin):
749
667
  f"[red]❌[/ red] {hook_type.title()} hooks failed: {summary['failed']} failed, {summary['errors']} errors",
750
668
  )
751
669
 
752
- # Try autofix for fast hooks before giving up
753
670
  if hook_type == "fast" and attempt < max_retries - 1:
754
671
  if self._attempt_autofix_for_fast_hooks(results):
755
672
  self.console.print(
756
673
  "[yellow]🔧[/ yellow] Applied autofixes for fast hooks, retrying...",
757
674
  )
758
- return True # Return True to continue the retry loop
675
+ return True
759
676
 
760
- # Display detailed hook errors in verbose mode
761
677
  if getattr(options, "verbose", False):
762
678
  self._display_verbose_hook_errors(results, hook_type)
763
679
 
@@ -772,13 +688,11 @@ class PhaseCoordinator(ErrorHandlingMixin):
772
688
  def _display_verbose_hook_errors(
773
689
  self, results: list[t.Any], hook_type: str
774
690
  ) -> None:
775
- """Display detailed hook error output in verbose mode."""
776
691
  self.console.print(
777
- f"\n[bold yellow]📋 Detailed {hook_type} hook errors:[/bold yellow]"
692
+ f"\n[bold yellow]📋 Detailed {hook_type} hook errors: [/bold yellow]"
778
693
  )
779
694
 
780
695
  for result in results:
781
- # Check if this hook failed
782
696
  status = getattr(result, "status", "")
783
697
  if status not in ("failed", "error", "timeout"):
784
698
  continue
@@ -791,12 +705,10 @@ class PhaseCoordinator(ErrorHandlingMixin):
791
705
  if issues:
792
706
  for issue in issues:
793
707
  if isinstance(issue, str) and issue.strip():
794
- # Clean up the issue text and display with proper indentation
795
708
  cleaned_issue = issue.strip()
796
- self.console.print(f" {cleaned_issue}")
709
+ self.console.print(f" {cleaned_issue}")
797
710
  else:
798
- # If no specific issues, show generic failure message
799
- self.console.print(f" Hook failed with exit code (status: {status})")
711
+ self.console.print(f" Hook failed with exit code (status: {status})")
800
712
 
801
713
  def _build_detailed_hook_error_message(
802
714
  self, results: list[t.Any], summary: dict[str, t.Any]
@@ -851,18 +763,15 @@ class PhaseCoordinator(ErrorHandlingMixin):
851
763
  self.session.fail_task(f"{hook_type}_hooks", str(e))
852
764
  return False
853
765
 
854
- # Performance-optimized hook execution methods
855
766
  async def _execute_hooks_with_parallel_support(
856
767
  self,
857
768
  hook_type: str,
858
769
  hook_runner: t.Callable[[], list[t.Any]],
859
770
  options: OptionsProtocol,
860
771
  ) -> bool:
861
- """Execute hooks with parallel optimization where safe."""
862
772
  self._initialize_hook_execution(hook_type)
863
773
 
864
774
  try:
865
- # Execute hooks and handle results
866
775
  return await self._process_parallel_hook_execution(
867
776
  hook_type, hook_runner, options
868
777
  )
@@ -876,16 +785,12 @@ class PhaseCoordinator(ErrorHandlingMixin):
876
785
  hook_runner: t.Callable[[], list[t.Any]],
877
786
  options: OptionsProtocol,
878
787
  ) -> bool:
879
- """Process hook execution with autofix retry logic."""
880
- # For now, maintain sequential execution for safety
881
- # Future enhancement: implement parallel execution for independent hooks
882
788
  results = hook_runner()
883
789
  summary = self.hook_manager.get_hook_summary(results)
884
790
 
885
791
  if not self._has_hook_failures(summary):
886
792
  return self._handle_hook_success(hook_type, summary)
887
793
 
888
- # Handle failures with potential autofix retry
889
794
  return self._handle_parallel_hook_failures(
890
795
  hook_type, hook_runner, options, results, summary
891
796
  )
@@ -898,19 +803,16 @@ class PhaseCoordinator(ErrorHandlingMixin):
898
803
  results: list[t.Any],
899
804
  summary: dict[str, t.Any],
900
805
  ) -> bool:
901
- """Handle hook failures with autofix retry for fast hooks."""
902
806
  if hook_type != "fast":
903
807
  return self._handle_hook_failures(
904
808
  hook_type, options, summary, results, 0, 1
905
809
  )
906
810
 
907
- # Try autofix for fast hooks
908
811
  if not self._attempt_autofix_for_fast_hooks(results):
909
812
  return self._handle_hook_failures(
910
813
  hook_type, options, summary, results, 0, 1
911
814
  )
912
815
 
913
- # Retry after successful autofix
914
816
  return self._retry_hooks_after_autofix(hook_type, hook_runner, options)
915
817
 
916
818
  def _retry_hooks_after_autofix(
@@ -919,12 +821,10 @@ class PhaseCoordinator(ErrorHandlingMixin):
919
821
  hook_runner: t.Callable[[], list[t.Any]],
920
822
  options: OptionsProtocol,
921
823
  ) -> bool:
922
- """Retry hooks after autofix was applied."""
923
824
  self.console.print(
924
825
  "[yellow]🔧[/ yellow] Applied autofixes for fast hooks, retrying..."
925
826
  )
926
827
 
927
- # Retry after autofix
928
828
  results = hook_runner()
929
829
  summary = self.hook_manager.get_hook_summary(results)
930
830
 
@@ -934,6 +834,6 @@ class PhaseCoordinator(ErrorHandlingMixin):
934
834
  return self._handle_hook_failures(hook_type, options, summary, results, 0, 1)
935
835
 
936
836
  @property
937
- def autofix_coordinator(self):
938
- """Lazy property for autofix coordinator."""
939
- return self._lazy_autofix.get()
837
+ def autofix_coordinator(self) -> AutofixCoordinator:
838
+ coordinator: AutofixCoordinator = self._lazy_autofix.get()
839
+ return coordinator