crackerjack 0.31.10__py3-none-any.whl → 0.31.12__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 (155) hide show
  1. crackerjack/CLAUDE.md +288 -705
  2. crackerjack/__main__.py +22 -8
  3. crackerjack/agents/__init__.py +0 -3
  4. crackerjack/agents/architect_agent.py +0 -43
  5. crackerjack/agents/base.py +1 -9
  6. crackerjack/agents/coordinator.py +2 -148
  7. crackerjack/agents/documentation_agent.py +109 -81
  8. crackerjack/agents/dry_agent.py +122 -97
  9. crackerjack/agents/formatting_agent.py +3 -16
  10. crackerjack/agents/import_optimization_agent.py +1174 -130
  11. crackerjack/agents/performance_agent.py +956 -188
  12. crackerjack/agents/performance_helpers.py +229 -0
  13. crackerjack/agents/proactive_agent.py +1 -48
  14. crackerjack/agents/refactoring_agent.py +516 -246
  15. crackerjack/agents/refactoring_helpers.py +282 -0
  16. crackerjack/agents/security_agent.py +393 -90
  17. crackerjack/agents/test_creation_agent.py +1776 -120
  18. crackerjack/agents/test_specialist_agent.py +59 -15
  19. crackerjack/agents/tracker.py +0 -102
  20. crackerjack/api.py +145 -37
  21. crackerjack/cli/handlers.py +48 -30
  22. crackerjack/cli/interactive.py +11 -11
  23. crackerjack/cli/options.py +66 -4
  24. crackerjack/code_cleaner.py +808 -148
  25. crackerjack/config/global_lock_config.py +110 -0
  26. crackerjack/config/hooks.py +43 -64
  27. crackerjack/core/async_workflow_orchestrator.py +247 -97
  28. crackerjack/core/autofix_coordinator.py +192 -109
  29. crackerjack/core/enhanced_container.py +46 -63
  30. crackerjack/core/file_lifecycle.py +549 -0
  31. crackerjack/core/performance.py +9 -8
  32. crackerjack/core/performance_monitor.py +395 -0
  33. crackerjack/core/phase_coordinator.py +281 -94
  34. crackerjack/core/proactive_workflow.py +9 -58
  35. crackerjack/core/resource_manager.py +501 -0
  36. crackerjack/core/service_watchdog.py +490 -0
  37. crackerjack/core/session_coordinator.py +4 -8
  38. crackerjack/core/timeout_manager.py +504 -0
  39. crackerjack/core/websocket_lifecycle.py +475 -0
  40. crackerjack/core/workflow_orchestrator.py +343 -209
  41. crackerjack/dynamic_config.py +47 -6
  42. crackerjack/errors.py +3 -4
  43. crackerjack/executors/async_hook_executor.py +63 -13
  44. crackerjack/executors/cached_hook_executor.py +14 -14
  45. crackerjack/executors/hook_executor.py +100 -37
  46. crackerjack/executors/hook_lock_manager.py +856 -0
  47. crackerjack/executors/individual_hook_executor.py +120 -86
  48. crackerjack/intelligence/__init__.py +0 -7
  49. crackerjack/intelligence/adaptive_learning.py +13 -86
  50. crackerjack/intelligence/agent_orchestrator.py +15 -78
  51. crackerjack/intelligence/agent_registry.py +12 -59
  52. crackerjack/intelligence/agent_selector.py +31 -92
  53. crackerjack/intelligence/integration.py +1 -41
  54. crackerjack/interactive.py +9 -9
  55. crackerjack/managers/async_hook_manager.py +25 -8
  56. crackerjack/managers/hook_manager.py +9 -9
  57. crackerjack/managers/publish_manager.py +57 -59
  58. crackerjack/managers/test_command_builder.py +6 -36
  59. crackerjack/managers/test_executor.py +9 -61
  60. crackerjack/managers/test_manager.py +17 -63
  61. crackerjack/managers/test_manager_backup.py +77 -127
  62. crackerjack/managers/test_progress.py +4 -23
  63. crackerjack/mcp/cache.py +5 -12
  64. crackerjack/mcp/client_runner.py +10 -10
  65. crackerjack/mcp/context.py +64 -6
  66. crackerjack/mcp/dashboard.py +14 -11
  67. crackerjack/mcp/enhanced_progress_monitor.py +55 -55
  68. crackerjack/mcp/file_monitor.py +72 -42
  69. crackerjack/mcp/progress_components.py +103 -84
  70. crackerjack/mcp/progress_monitor.py +122 -49
  71. crackerjack/mcp/rate_limiter.py +12 -12
  72. crackerjack/mcp/server_core.py +16 -22
  73. crackerjack/mcp/service_watchdog.py +26 -26
  74. crackerjack/mcp/state.py +15 -0
  75. crackerjack/mcp/tools/core_tools.py +95 -39
  76. crackerjack/mcp/tools/error_analyzer.py +6 -32
  77. crackerjack/mcp/tools/execution_tools.py +1 -56
  78. crackerjack/mcp/tools/execution_tools_backup.py +35 -131
  79. crackerjack/mcp/tools/intelligence_tool_registry.py +0 -36
  80. crackerjack/mcp/tools/intelligence_tools.py +2 -55
  81. crackerjack/mcp/tools/monitoring_tools.py +308 -145
  82. crackerjack/mcp/tools/proactive_tools.py +12 -42
  83. crackerjack/mcp/tools/progress_tools.py +23 -15
  84. crackerjack/mcp/tools/utility_tools.py +3 -40
  85. crackerjack/mcp/tools/workflow_executor.py +40 -60
  86. crackerjack/mcp/websocket/app.py +0 -3
  87. crackerjack/mcp/websocket/endpoints.py +206 -268
  88. crackerjack/mcp/websocket/jobs.py +213 -66
  89. crackerjack/mcp/websocket/server.py +84 -6
  90. crackerjack/mcp/websocket/websocket_handler.py +137 -29
  91. crackerjack/models/config_adapter.py +3 -16
  92. crackerjack/models/protocols.py +162 -3
  93. crackerjack/models/resource_protocols.py +454 -0
  94. crackerjack/models/task.py +3 -3
  95. crackerjack/monitoring/__init__.py +0 -0
  96. crackerjack/monitoring/ai_agent_watchdog.py +25 -71
  97. crackerjack/monitoring/regression_prevention.py +28 -87
  98. crackerjack/orchestration/advanced_orchestrator.py +44 -78
  99. crackerjack/orchestration/coverage_improvement.py +10 -60
  100. crackerjack/orchestration/execution_strategies.py +16 -16
  101. crackerjack/orchestration/test_progress_streamer.py +61 -53
  102. crackerjack/plugins/base.py +1 -1
  103. crackerjack/plugins/managers.py +22 -20
  104. crackerjack/py313.py +65 -21
  105. crackerjack/services/backup_service.py +467 -0
  106. crackerjack/services/bounded_status_operations.py +627 -0
  107. crackerjack/services/cache.py +7 -9
  108. crackerjack/services/config.py +35 -52
  109. crackerjack/services/config_integrity.py +5 -16
  110. crackerjack/services/config_merge.py +542 -0
  111. crackerjack/services/contextual_ai_assistant.py +17 -19
  112. crackerjack/services/coverage_ratchet.py +44 -73
  113. crackerjack/services/debug.py +25 -39
  114. crackerjack/services/dependency_monitor.py +52 -50
  115. crackerjack/services/enhanced_filesystem.py +14 -11
  116. crackerjack/services/file_hasher.py +1 -1
  117. crackerjack/services/filesystem.py +1 -12
  118. crackerjack/services/git.py +71 -47
  119. crackerjack/services/health_metrics.py +31 -27
  120. crackerjack/services/initialization.py +276 -428
  121. crackerjack/services/input_validator.py +760 -0
  122. crackerjack/services/log_manager.py +16 -16
  123. crackerjack/services/logging.py +7 -6
  124. crackerjack/services/metrics.py +43 -43
  125. crackerjack/services/pattern_cache.py +2 -31
  126. crackerjack/services/pattern_detector.py +26 -63
  127. crackerjack/services/performance_benchmarks.py +20 -45
  128. crackerjack/services/regex_patterns.py +2887 -0
  129. crackerjack/services/regex_utils.py +537 -0
  130. crackerjack/services/secure_path_utils.py +683 -0
  131. crackerjack/services/secure_status_formatter.py +534 -0
  132. crackerjack/services/secure_subprocess.py +605 -0
  133. crackerjack/services/security.py +47 -10
  134. crackerjack/services/security_logger.py +492 -0
  135. crackerjack/services/server_manager.py +109 -50
  136. crackerjack/services/smart_scheduling.py +8 -25
  137. crackerjack/services/status_authentication.py +603 -0
  138. crackerjack/services/status_security_manager.py +442 -0
  139. crackerjack/services/thread_safe_status_collector.py +546 -0
  140. crackerjack/services/tool_version_service.py +1 -23
  141. crackerjack/services/unified_config.py +36 -58
  142. crackerjack/services/validation_rate_limiter.py +269 -0
  143. crackerjack/services/version_checker.py +9 -40
  144. crackerjack/services/websocket_resource_limiter.py +572 -0
  145. crackerjack/slash_commands/__init__.py +52 -2
  146. crackerjack/tools/__init__.py +0 -0
  147. crackerjack/tools/validate_input_validator_patterns.py +262 -0
  148. crackerjack/tools/validate_regex_patterns.py +198 -0
  149. {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/METADATA +197 -12
  150. crackerjack-0.31.12.dist-info/RECORD +178 -0
  151. crackerjack/cli/facade.py +0 -104
  152. crackerjack-0.31.10.dist-info/RECORD +0 -149
  153. {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/WHEEL +0 -0
  154. {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/entry_points.txt +0 -0
  155. {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/licenses/LICENSE +0 -0
@@ -33,7 +33,6 @@ def _register_execute_crackerjack_tool(mcp_app: t.Any) -> None:
33
33
 
34
34
  extra_kwargs = kwargs_result["kwargs"]
35
35
 
36
- # Run the workflow directly instead of in background
37
36
  try:
38
37
  result = await _execute_crackerjack_sync(
39
38
  job_id,
@@ -78,7 +77,6 @@ async def _validate_context_and_rate_limit(context: t.Any) -> str | None:
78
77
  if not context:
79
78
  return '{"error": "Server context not available"}'
80
79
 
81
- # Rate limiting is optional - skip if not configured
82
80
  if context.rate_limiter:
83
81
  allowed, details = await context.rate_limiter.check_request_allowed("default")
84
82
  if not allowed:
@@ -88,16 +86,14 @@ async def _validate_context_and_rate_limit(context: t.Any) -> str | None:
88
86
 
89
87
 
90
88
  def _handle_task_exception(job_id: str, task: asyncio.Task) -> None:
91
- """Handle exceptions from background tasks."""
92
89
  import tempfile
93
90
  from pathlib import Path
94
91
 
95
92
  try:
96
93
  exception = task.exception()
97
94
  if exception:
98
- # Log the exception to a debug file
99
95
  debug_file = (
100
- Path(tempfile.gettempdir()) / f"crackerjack-task-error-{job_id}.log"
96
+ Path(tempfile.gettempdir()) / f"crackerjack - task-error -{job_id}.log"
101
97
  )
102
98
  with debug_file.open("w") as f:
103
99
  f.write(
@@ -107,13 +103,13 @@ def _handle_task_exception(job_id: str, task: asyncio.Task) -> None:
107
103
  import traceback
108
104
 
109
105
  f.write(
110
- f"Traceback:\n{traceback.format_exception(type(exception), exception, exception.__traceback__)}\n",
106
+ f"Traceback: \n{traceback.format_exception(type(exception), exception, exception.__traceback__)}\n",
111
107
  )
112
108
  except Exception as e:
113
- # If we can't even log the error, at least try to create a simple file
114
109
  with suppress(Exception):
115
110
  debug_file = (
116
- Path(tempfile.gettempdir()) / f"crackerjack-logging-error-{job_id}.log"
111
+ Path(tempfile.gettempdir())
112
+ / f"crackerjack - logging-error -{job_id}.log"
117
113
  )
118
114
  with debug_file.open("w") as f:
119
115
  f.write(f"Failed to log task exception: {e}\n")
@@ -220,7 +216,6 @@ async def _initialize_execution(
220
216
  current_iteration: int,
221
217
  context: t.Any,
222
218
  ) -> None:
223
- """Initialize execution with status checks and service preparation."""
224
219
  _update_progress(
225
220
  job_id=job_id,
226
221
  iteration=current_iteration,
@@ -229,7 +224,6 @@ async def _initialize_execution(
229
224
  message="Initializing crackerjack execution",
230
225
  )
231
226
 
232
- # Check comprehensive status first to prevent conflicts and perform cleanup
233
227
  status_result = await _check_status_and_prepare(job_id, context)
234
228
  if status_result.get("should_abort", False):
235
229
  msg = f"Execution aborted: {status_result['reason']}"
@@ -241,13 +235,11 @@ async def _initialize_execution(
241
235
  max_iterations=max_iterations,
242
236
  overall_progress=5,
243
237
  current_stage="status_verified",
244
- message="Status check complete - no conflicts detected",
238
+ message="Status check complete-no conflicts detected",
245
239
  )
246
240
 
247
- # Clean up stale jobs first
248
241
  await _cleanup_stale_jobs(context)
249
242
 
250
- # Auto-start required services
251
243
  await _ensure_services_running(job_id, context)
252
244
 
253
245
  _update_progress(
@@ -267,13 +259,10 @@ async def _setup_orchestrator(
267
259
  kwargs: dict[str, t.Any],
268
260
  context: t.Any,
269
261
  ) -> tuple[t.Any, bool]:
270
- """Set up the appropriate orchestrator (force standard for MCP compatibility)."""
271
- # Force standard orchestrator for MCP server to ensure proper progress reporting
272
262
  context.safe_print("Using Standard WorkflowOrchestrator for MCP compatibility")
273
263
  orchestrator = _create_standard_orchestrator(job_id, kwargs, context)
274
264
  use_advanced_orchestrator = False
275
265
 
276
- # Update progress to show orchestrator mode
277
266
  orchestrator_type = "Standard Orchestrator (MCP Compatible)"
278
267
  _update_progress(
279
268
  job_id=job_id,
@@ -292,7 +281,6 @@ async def _create_advanced_orchestrator(
292
281
  kwargs: dict[str, t.Any],
293
282
  context: t.Any,
294
283
  ) -> t.Any:
295
- """Create and configure the advanced orchestrator."""
296
284
  from crackerjack.core.session_coordinator import SessionCoordinator
297
285
  from crackerjack.orchestration.advanced_orchestrator import (
298
286
  AdvancedWorkflowOrchestrator,
@@ -306,28 +294,23 @@ async def _create_advanced_orchestrator(
306
294
  StreamingMode,
307
295
  )
308
296
 
309
- # Create optimal orchestration configuration for maximum efficiency
310
297
  optimal_config = OrchestrationConfig(
311
298
  execution_strategy=ExecutionStrategy.ADAPTIVE,
312
299
  progress_level=ProgressLevel.DETAILED,
313
300
  streaming_mode=StreamingMode.WEBSOCKET,
314
301
  ai_coordination_mode=AICoordinationMode.COORDINATOR,
315
302
  ai_intelligence=AIIntelligence.ADAPTIVE,
316
- # Enable advanced features
317
303
  correlation_tracking=True,
318
304
  failure_analysis=True,
319
305
  intelligent_retry=True,
320
- # Maximize parallelism for hook and test fixing
321
306
  max_parallel_hooks=3,
322
307
  max_parallel_tests=4,
323
308
  timeout_multiplier=1.0,
324
- # Enhanced debugging and monitoring
325
309
  debug_level="standard",
326
310
  log_individual_outputs=False,
327
311
  preserve_temp_files=False,
328
312
  )
329
313
 
330
- # Initialize advanced orchestrator with optimal config
331
314
  session = SessionCoordinator(
332
315
  context.console,
333
316
  context.config.project_path,
@@ -340,10 +323,9 @@ async def _create_advanced_orchestrator(
340
323
  config=optimal_config,
341
324
  )
342
325
 
343
- # Override MCP mode if debug flag is set
344
326
  if kwargs.get("debug", False):
345
327
  orchestrator.individual_executor.set_mcp_mode(False)
346
- context.safe_print("🐛 Debug mode enabled - full output mode")
328
+ context.safe_print("🐛 Debug mode enabled-full output mode")
347
329
 
348
330
  return orchestrator
349
331
 
@@ -353,7 +335,6 @@ def _create_standard_orchestrator(
353
335
  kwargs: dict[str, t.Any],
354
336
  context: t.Any,
355
337
  ) -> t.Any:
356
- """Create the standard fallback orchestrator."""
357
338
  from crackerjack.core.workflow_orchestrator import WorkflowOrchestrator
358
339
 
359
340
  return WorkflowOrchestrator(
@@ -371,7 +352,6 @@ async def _run_workflow_iterations(
371
352
  use_advanced_orchestrator: bool,
372
353
  kwargs: dict[str, t.Any],
373
354
  ) -> dict[str, t.Any]:
374
- """Run the main workflow iteration loop."""
375
355
  success = False
376
356
  current_iteration = 1
377
357
 
@@ -421,14 +401,13 @@ async def _run_workflow_iterations(
421
401
 
422
402
 
423
403
  def _create_workflow_options(kwargs: dict[str, t.Any]) -> t.Any:
424
- """Create WorkflowOptions from kwargs."""
425
404
  from crackerjack.models.config import WorkflowOptions
426
405
 
427
406
  options = WorkflowOptions()
428
407
  options.testing.test = kwargs.get("test", True)
429
408
  options.ai_agent = kwargs.get("ai_agent", True)
430
409
  options.skip_hooks = kwargs.get("skip_hooks", False)
431
- # Enable proactive mode by default for better architectural planning
410
+
432
411
  options.proactive_mode = kwargs.get("proactive_mode", True)
433
412
  return options
434
413
 
@@ -438,7 +417,6 @@ async def _execute_single_iteration(
438
417
  use_advanced_orchestrator: bool,
439
418
  options: t.Any,
440
419
  ) -> bool:
441
- """Execute a single workflow iteration."""
442
420
  if use_advanced_orchestrator:
443
421
  return await orchestrator.execute_orchestrated_workflow(options)
444
422
  return await orchestrator.run_complete_workflow(options)
@@ -450,7 +428,6 @@ def _create_success_result(
450
428
  max_iterations: int,
451
429
  iteration: int,
452
430
  ) -> dict[str, t.Any]:
453
- """Create success result dictionary."""
454
431
  _update_progress(
455
432
  job_id=job_id,
456
433
  status="completed",
@@ -474,7 +451,6 @@ async def _handle_iteration_retry(
474
451
  max_iterations: int,
475
452
  iteration: int,
476
453
  ) -> None:
477
- """Handle iteration retry logic."""
478
454
  _update_progress(
479
455
  job_id=job_id,
480
456
  iteration=current_iteration,
@@ -491,7 +467,6 @@ async def _handle_iteration_error(
491
467
  max_iterations: int,
492
468
  error: Exception,
493
469
  ) -> bool:
494
- """Handle iteration errors. Returns True to continue, False to break."""
495
470
  if iteration >= max_iterations:
496
471
  return False
497
472
  await asyncio.sleep(1)
@@ -503,7 +478,6 @@ def _create_failure_result(
503
478
  current_iteration: int,
504
479
  max_iterations: int,
505
480
  ) -> dict[str, t.Any]:
506
- """Create failure result dictionary."""
507
481
  _update_progress(
508
482
  job_id=job_id,
509
483
  status="failed",
@@ -522,7 +496,6 @@ def _create_failure_result(
522
496
 
523
497
 
524
498
  async def _ensure_services_running(job_id: str, context: t.Any) -> None:
525
- """Ensure WebSocket server and watchdog are running before starting workflow."""
526
499
  import subprocess
527
500
 
528
501
  _update_progress(
@@ -531,7 +504,6 @@ async def _ensure_services_running(job_id: str, context: t.Any) -> None:
531
504
  message="Checking required services...",
532
505
  )
533
506
 
534
- # Check if WebSocket server is running
535
507
  websocket_running = False
536
508
  with suppress(Exception):
537
509
  from crackerjack.services.server_manager import find_websocket_server_processes
@@ -547,16 +519,14 @@ async def _ensure_services_running(job_id: str, context: t.Any) -> None:
547
519
  )
548
520
 
549
521
  try:
550
- # Start WebSocket server in background
551
522
  subprocess.Popen(
552
- ["python", "-m", "crackerjack", "--start-websocket-server"],
523
+ ["python", "- m", "crackerjack", "- - start - websocket-server"],
553
524
  cwd=context.config.project_path,
554
525
  stdout=subprocess.DEVNULL,
555
526
  stderr=subprocess.DEVNULL,
556
527
  start_new_session=True,
557
528
  )
558
529
 
559
- # Wait for server to start
560
530
  for _i in range(10):
561
531
  with suppress(Exception):
562
532
  websocket_processes = find_websocket_server_processes()
@@ -574,7 +544,6 @@ async def _ensure_services_running(job_id: str, context: t.Any) -> None:
574
544
 
575
545
 
576
546
  async def _check_status_and_prepare(job_id: str, context: t.Any) -> dict[str, t.Any]:
577
- """Check comprehensive system status and prepare for execution."""
578
547
  _update_progress(
579
548
  job_id=job_id,
580
549
  current_stage="status_check",
@@ -588,16 +557,13 @@ async def _check_status_and_prepare(job_id: str, context: t.Any) -> dict[str, t.
588
557
 
589
558
  cleanup_performed = []
590
559
 
591
- # Check for conflicting jobs
592
560
  _check_active_jobs(status_info, context)
593
561
 
594
- # Check and flag resource cleanup needs
595
562
  cleanup_performed.extend(_check_resource_cleanup(status_info, context))
596
563
 
597
- # Check service health
598
564
  _check_service_health(status_info, context)
599
565
 
600
- context.safe_print("✅ Status check complete - ready to proceed")
566
+ context.safe_print("✅ Status check complete-ready to proceed")
601
567
 
602
568
  return {
603
569
  "should_abort": False,
@@ -611,7 +577,6 @@ async def _check_status_and_prepare(job_id: str, context: t.Any) -> dict[str, t.
611
577
 
612
578
 
613
579
  async def _get_status_info() -> dict[str, t.Any]:
614
- """Get comprehensive system status."""
615
580
  from .monitoring_tools import _get_comprehensive_status
616
581
 
617
582
  return await _get_comprehensive_status()
@@ -621,7 +586,6 @@ def _handle_status_error(
621
586
  status_info: dict[str, t.Any],
622
587
  context: t.Any,
623
588
  ) -> dict[str, t.Any]:
624
- """Handle status check failure."""
625
589
  context.safe_print(f"⚠️ Status check failed: {status_info['error']}")
626
590
  return {
627
591
  "should_abort": False,
@@ -632,7 +596,6 @@ def _handle_status_error(
632
596
 
633
597
 
634
598
  def _check_active_jobs(status_info: dict[str, t.Any], context: t.Any) -> None:
635
- """Check for active jobs that might conflict."""
636
599
  active_jobs = [
637
600
  j
638
601
  for j in status_info.get("jobs", {}).get("details", [])
@@ -642,15 +605,13 @@ def _check_active_jobs(status_info: dict[str, t.Any], context: t.Any) -> None:
642
605
  if active_jobs:
643
606
  _handle_conflicting_jobs(active_jobs, context)
644
607
  else:
645
- context.safe_print("✅ No active jobs detected - safe to proceed")
608
+ context.safe_print("✅ No active jobs detected-safe to proceed")
646
609
 
647
610
 
648
611
  def _handle_conflicting_jobs(
649
612
  active_jobs: list[dict[str, t.Any]],
650
613
  context: t.Any,
651
614
  ) -> None:
652
- """Handle conflicting active jobs."""
653
- # For now, assume all jobs could conflict (future: check project paths)
654
615
  conflicting_jobs = active_jobs
655
616
 
656
617
  if conflicting_jobs:
@@ -659,13 +620,12 @@ def _handle_conflicting_jobs(
659
620
  f"⚠️ Found {len(conflicting_jobs)} active job(s): {', '.join(job_ids[:3])}",
660
621
  )
661
622
  context.safe_print(
662
- " Running concurrent crackerjack instances may cause file conflicts",
623
+ " Running concurrent crackerjack instances may cause file conflicts",
663
624
  )
664
- context.safe_print(" Proceeding with caution...")
625
+ context.safe_print(" Proceeding with caution...")
665
626
 
666
627
 
667
628
  def _check_resource_cleanup(status_info: dict[str, t.Any], context: t.Any) -> list[str]:
668
- """Check if resource cleanup is needed."""
669
629
  cleanup_performed = []
670
630
 
671
631
  temp_files_count = (
@@ -676,7 +636,7 @@ def _check_resource_cleanup(status_info: dict[str, t.Any], context: t.Any) -> li
676
636
 
677
637
  if temp_files_count > 50:
678
638
  context.safe_print(
679
- f"🗑️ Found {temp_files_count} temporary files - cleanup recommended",
639
+ f"🗑️ Found {temp_files_count} temporary files-cleanup recommended",
680
640
  )
681
641
  cleanup_performed.append("temp_files_flagged")
682
642
 
@@ -684,7 +644,6 @@ def _check_resource_cleanup(status_info: dict[str, t.Any], context: t.Any) -> li
684
644
 
685
645
 
686
646
  def _check_service_health(status_info: dict[str, t.Any], context: t.Any) -> None:
687
- """Check health of required services."""
688
647
  services = status_info.get("services", {})
689
648
  mcp_running = services.get("mcp_server", {}).get("running", False)
690
649
  websocket_running = services.get("websocket_server", {}).get("running", False)
@@ -697,7 +656,6 @@ def _check_service_health(status_info: dict[str, t.Any], context: t.Any) -> None
697
656
 
698
657
 
699
658
  def _handle_status_exception(error: Exception, context: t.Any) -> dict[str, t.Any]:
700
- """Handle status check exceptions."""
701
659
  context.safe_print(f"⚠️ Status check encountered error: {error}")
702
660
  return {
703
661
  "should_abort": False,
@@ -708,7 +666,6 @@ def _handle_status_exception(error: Exception, context: t.Any) -> dict[str, t.An
708
666
 
709
667
 
710
668
  async def _cleanup_stale_jobs(context: t.Any) -> None:
711
- """Clean up stale job files with unknown IDs or stuck in processing state."""
712
669
  if not context.progress_dir.exists():
713
670
  return
714
671
 
@@ -722,15 +679,14 @@ async def _cleanup_stale_jobs(context: t.Any) -> None:
722
679
 
723
680
  progress_data = json.loads(progress_file.read_text())
724
681
 
725
- # Check if job is stale (older than 30 minutes and stuck)
726
682
  last_update = progress_data.get("updated_at", 0)
727
683
  age_minutes = (current_time - last_update) / 60
728
684
 
729
685
  is_stale = (
730
- age_minutes > 30 # Older than 30 minutes
731
- or progress_data.get("job_id") == "unknown" # Unknown job ID
686
+ age_minutes > 30
687
+ or progress_data.get("job_id") == "unknown"
732
688
  or "analyzing_failures: processing"
733
- in progress_data.get("status", "") # Stuck in processing
689
+ in progress_data.get("status", "")
734
690
  )
735
691
 
736
692
  if is_stale:
@@ -738,7 +694,6 @@ async def _cleanup_stale_jobs(context: t.Any) -> None:
738
694
  cleaned_count += 1
739
695
 
740
696
  except (json.JSONDecodeError, OSError):
741
- # Clean up malformed files
742
697
  with suppress(OSError):
743
698
  progress_file.unlink()
744
699
  cleaned_count += 1
@@ -750,15 +705,6 @@ async def _cleanup_stale_jobs(context: t.Any) -> None:
750
705
  def _register_init_crackerjack_tool(mcp_app: t.Any) -> None:
751
706
  @mcp_app.tool()
752
707
  async def init_crackerjack(args: str = "", kwargs: str = "{}") -> str:
753
- """Initialize or update crackerjack configuration in current project.
754
-
755
- Args:
756
- args: Optional target path (defaults to current directory)
757
- kwargs: JSON string with options like {"force": true}
758
-
759
- Returns:
760
- JSON string with initialization results
761
- """
762
708
  context = get_context()
763
709
  if not context:
764
710
  return _create_init_error_response("Server context not available")
@@ -775,12 +721,10 @@ def _register_init_crackerjack_tool(mcp_app: t.Any) -> None:
775
721
 
776
722
 
777
723
  def _create_init_error_response(message: str) -> str:
778
- """Create standardized error response for initialization."""
779
724
  return json.dumps({"error": message, "success": False}, indent=2)
780
725
 
781
726
 
782
727
  def _parse_init_arguments(args: str, kwargs: str) -> tuple[t.Any, bool, str | None]:
783
- """Parse and validate initialization arguments."""
784
728
  from pathlib import Path
785
729
 
786
730
  target_path = args.strip() or None
@@ -792,13 +736,11 @@ def _parse_init_arguments(args: str, kwargs: str) -> tuple[t.Any, bool, str | No
792
736
 
793
737
  force = extra_kwargs.get("force", False)
794
738
 
795
- # Determine target path
796
739
  if target_path:
797
740
  target_path = Path(target_path).resolve()
798
741
  else:
799
742
  target_path = Path.cwd()
800
743
 
801
- # Validate target path exists
802
744
  if not target_path.exists():
803
745
  return (
804
746
  None,
@@ -812,15 +754,13 @@ def _parse_init_arguments(args: str, kwargs: str) -> tuple[t.Any, bool, str | No
812
754
  def _execute_initialization(
813
755
  context: t.Any, target_path: t.Any, force: bool
814
756
  ) -> dict[str, t.Any]:
815
- """Execute the initialization process."""
816
757
  from crackerjack.services.filesystem import FileSystemService
817
758
  from crackerjack.services.git import GitService
818
759
  from crackerjack.services.initialization import InitializationService
819
760
 
820
- # Initialize services
821
761
  filesystem = FileSystemService()
822
762
  git_service = GitService(context.console, context.config.project_path)
823
- # Run initialization
763
+
824
764
  return InitializationService(
825
765
  context.console, filesystem, git_service, context.config.project_path
826
766
  ).initialize_project(target_path=target_path, force=force)
@@ -829,7 +769,6 @@ def _execute_initialization(
829
769
  def _create_init_success_response(
830
770
  results: dict[str, t.Any], target_path: t.Any, force: bool
831
771
  ) -> str:
832
- """Create success response with summary information."""
833
772
  results["command"] = "init_crackerjack"
834
773
  results["target_path"] = str(target_path)
835
774
  results["force"] = force
@@ -837,7 +776,6 @@ def _create_init_success_response(
837
776
 
838
777
 
839
778
  def _create_init_exception_response(error: Exception, target_path: t.Any) -> str:
840
- """Create exception response for initialization failures."""
841
779
  error_result = {
842
780
  "error": f"Initialization failed: {error}",
843
781
  "success": False,
@@ -848,24 +786,12 @@ def _create_init_exception_response(error: Exception, target_path: t.Any) -> str
848
786
 
849
787
 
850
788
  def _register_agent_suggestions_tool(mcp_app: t.Any) -> None:
851
- """Register tool for suggesting appropriate Claude Code agents."""
852
-
853
789
  @mcp_app.tool()
854
790
  async def suggest_agents(
855
791
  task_description: str = "",
856
792
  project_type: str = "python",
857
793
  current_context: str = "",
858
794
  ) -> str:
859
- """Suggest appropriate Claude Code agents based on task and context.
860
-
861
- Args:
862
- task_description: Description of the task being performed
863
- project_type: Type of project (python, web, etc.)
864
- current_context: Current development context or issues
865
-
866
- Returns:
867
- JSON with suggested agents and usage patterns
868
- """
869
795
  suggestions = {
870
796
  "primary_agents": [],
871
797
  "task_specific_agents": [],
@@ -873,7 +799,6 @@ def _register_agent_suggestions_tool(mcp_app: t.Any) -> None:
873
799
  "rationale": "",
874
800
  }
875
801
 
876
- # Always recommend crackerjack-architect for Python projects
877
802
  if project_type.lower() == "python" or "python" in task_description.lower():
878
803
  suggestions["primary_agents"].append(
879
804
  {
@@ -889,13 +814,12 @@ def _register_agent_suggestions_tool(mcp_app: t.Any) -> None:
889
814
  {
890
815
  "name": "python-pro",
891
816
  "emoji": "🐍",
892
- "description": "Modern Python development with type hints, async/await patterns, and clean architecture",
817
+ "description": "Modern Python development with type hints, async / await patterns, and clean architecture",
893
818
  "usage": "Use for implementing Python code with best practices",
894
819
  "priority": "HIGH",
895
820
  }
896
821
  )
897
822
 
898
- # Task-specific agent suggestions
899
823
  task_lower = task_description.lower()
900
824
  context_lower = current_context.lower()
901
825
 
@@ -905,7 +829,7 @@ def _register_agent_suggestions_tool(mcp_app: t.Any) -> None:
905
829
  ):
906
830
  suggestions["task_specific_agents"].append(
907
831
  {
908
- "name": "crackerjack-test-specialist",
832
+ "name": "crackerjack - test-specialist",
909
833
  "emoji": "🧪",
910
834
  "description": "Advanced testing specialist for complex scenarios and coverage optimization",
911
835
  "usage": "Use for test creation, debugging test failures, and coverage improvements",
@@ -915,7 +839,7 @@ def _register_agent_suggestions_tool(mcp_app: t.Any) -> None:
915
839
 
916
840
  suggestions["task_specific_agents"].append(
917
841
  {
918
- "name": "pytest-hypothesis-specialist",
842
+ "name": "pytest - hypothesis-specialist",
919
843
  "emoji": "🧪",
920
844
  "description": "Advanced testing patterns and property-based testing",
921
845
  "usage": "Use for comprehensive test development and optimization",
@@ -951,22 +875,20 @@ def _register_agent_suggestions_tool(mcp_app: t.Any) -> None:
951
875
  }
952
876
  )
953
877
 
954
- # Usage patterns
955
878
  suggestions["usage_patterns"] = [
956
- 'Task tool with subagent_type="crackerjack-architect" for feature planning and architecture',
957
- 'Task tool with subagent_type="python-pro" for implementation with best practices',
958
- 'Task tool with subagent_type="crackerjack-test-specialist" for comprehensive testing',
959
- 'Task tool with subagent_type="security-auditor" for security validation',
879
+ 'Task tool with subagent_type ="crackerjack-architect" for feature planning and architecture',
880
+ 'Task tool with subagent_type ="python-pro" for implementation with best practices',
881
+ 'Task tool with subagent_type ="crackerjack - test-specialist" for comprehensive testing',
882
+ 'Task tool with subagent_type ="security-auditor" for security validation',
960
883
  ]
961
884
 
962
- # Rationale
963
885
  if "crackerjack-architect" in [
964
886
  agent["name"] for agent in suggestions["primary_agents"]
965
887
  ]:
966
888
  suggestions["rationale"] = (
967
889
  "The crackerjack-architect agent is essential for this Python project as it ensures "
968
890
  "code follows crackerjack patterns from the start, eliminating retrofitting needs. "
969
- "Combined with python-pro for implementation and task-specific agents for specialized "
891
+ "Combined with python - pro for implementation and task-specific agents for specialized "
970
892
  "work, this provides comprehensive development support with built-in quality assurance."
971
893
  )
972
894
 
@@ -978,16 +900,6 @@ def _register_agent_suggestions_tool(mcp_app: t.Any) -> None:
978
900
  file_patterns: str = "",
979
901
  recent_changes: str = "",
980
902
  ) -> str:
981
- """Detect and suggest agents based on current development context.
982
-
983
- Args:
984
- error_context: Current errors or issues being faced
985
- file_patterns: File types or patterns being worked on
986
- recent_changes: Recent changes or commits
987
-
988
- Returns:
989
- JSON with agent recommendations based on context analysis
990
- """
991
903
  recommendations = {
992
904
  "urgent_agents": [],
993
905
  "suggested_agents": [],
@@ -995,16 +907,12 @@ def _register_agent_suggestions_tool(mcp_app: t.Any) -> None:
995
907
  "detection_reasoning": "",
996
908
  }
997
909
 
998
- # Add urgent agents based on error context
999
910
  _add_urgent_agents_for_errors(recommendations, error_context)
1000
911
 
1001
- # Add general suggestions for Python projects
1002
912
  _add_python_project_suggestions(recommendations, file_patterns)
1003
913
 
1004
- # Set workflow recommendations
1005
914
  _set_workflow_recommendations(recommendations)
1006
915
 
1007
- # Generate detection reasoning
1008
916
  _generate_detection_reasoning(recommendations)
1009
917
 
1010
918
  return json.dumps(recommendations, indent=2)
@@ -1013,16 +921,15 @@ def _register_agent_suggestions_tool(mcp_app: t.Any) -> None:
1013
921
  def _add_urgent_agents_for_errors(
1014
922
  recommendations: dict[str, t.Any], error_context: str
1015
923
  ) -> None:
1016
- """Add urgent agent recommendations based on error context."""
1017
924
  if any(
1018
925
  word in error_context.lower()
1019
926
  for word in ("test fail", "coverage", "pytest", "assertion")
1020
927
  ):
1021
928
  recommendations["urgent_agents"].append(
1022
929
  {
1023
- "agent": "crackerjack-test-specialist",
1024
- "reason": "Test failures detected - specialist needed for debugging and fixes",
1025
- "action": 'Task tool with subagent_type="crackerjack-test-specialist" to analyze and fix test issues',
930
+ "agent": "crackerjack - test-specialist",
931
+ "reason": "Test failures detected-specialist needed for debugging and fixes",
932
+ "action": 'Task tool with subagent_type ="crackerjack - test-specialist" to analyze and fix test issues',
1026
933
  }
1027
934
  )
1028
935
 
@@ -1033,8 +940,8 @@ def _add_urgent_agents_for_errors(
1033
940
  recommendations["urgent_agents"].append(
1034
941
  {
1035
942
  "agent": "security-auditor",
1036
- "reason": "Security issues detected - immediate audit required",
1037
- "action": 'Task tool with subagent_type="security-auditor" to review and fix security vulnerabilities',
943
+ "reason": "Security issues detected-immediate audit required",
944
+ "action": 'Task tool with subagent_type ="security-auditor" to review and fix security vulnerabilities',
1038
945
  }
1039
946
  )
1040
947
 
@@ -1045,8 +952,8 @@ def _add_urgent_agents_for_errors(
1045
952
  recommendations["urgent_agents"].append(
1046
953
  {
1047
954
  "agent": "crackerjack-architect",
1048
- "reason": "Complexity issues detected - architectural review needed",
1049
- "action": 'Task tool with subagent_type="crackerjack-architect" to simplify and restructure code',
955
+ "reason": "Complexity issues detected-architectural review needed",
956
+ "action": 'Task tool with subagent_type ="crackerjack-architect" to simplify and restructure code',
1050
957
  }
1051
958
  )
1052
959
 
@@ -1054,13 +961,12 @@ def _add_urgent_agents_for_errors(
1054
961
  def _add_python_project_suggestions(
1055
962
  recommendations: dict[str, t.Any], file_patterns: str
1056
963
  ) -> None:
1057
- """Add general suggestions for Python projects."""
1058
964
  if "python" in file_patterns.lower() or ".py" in file_patterns:
1059
965
  recommendations["suggested_agents"].extend(
1060
966
  [
1061
967
  {
1062
968
  "agent": "crackerjack-architect",
1063
- "reason": "Python project detected - ensure crackerjack compliance",
969
+ "reason": "Python project detected-ensure crackerjack compliance",
1064
970
  "priority": "HIGH",
1065
971
  },
1066
972
  {
@@ -1073,23 +979,21 @@ def _add_python_project_suggestions(
1073
979
 
1074
980
 
1075
981
  def _set_workflow_recommendations(recommendations: dict[str, t.Any]) -> None:
1076
- """Set workflow recommendations based on urgent agents."""
1077
982
  if recommendations["urgent_agents"]:
1078
983
  recommendations["workflow_recommendations"] = [
1079
984
  "Address urgent issues first with specialized agents",
1080
- "Run crackerjack quality checks after fixes: python -m crackerjack -t",
985
+ "Run crackerjack quality checks after fixes: python - m crackerjack-t",
1081
986
  "Use crackerjack-architect for ongoing compliance",
1082
987
  ]
1083
988
  else:
1084
989
  recommendations["workflow_recommendations"] = [
1085
990
  "Start with crackerjack-architect for proper planning",
1086
991
  "Use python-pro for implementation",
1087
- "Run continuous quality checks: python -m crackerjack",
992
+ "Run continuous quality checks: python-m crackerjack",
1088
993
  ]
1089
994
 
1090
995
 
1091
996
  def _generate_detection_reasoning(recommendations: dict[str, t.Any]) -> None:
1092
- """Generate detection reasoning based on recommendations."""
1093
997
  recommendations["detection_reasoning"] = (
1094
998
  f"Analysis of context revealed {len(recommendations['urgent_agents'])} urgent issues "
1095
999
  f"and {len(recommendations['suggested_agents'])} general recommendations. "