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
@@ -1,10 +1,7 @@
1
1
  import typing as t
2
2
 
3
- # Helper functions for creating responses and assessments
4
-
5
3
 
6
4
  def _create_architectural_assessment(args: str, parsed_kwargs: dict) -> dict:
7
- """Create architectural assessment with recommendations."""
8
5
  assessment = {
9
6
  "feature": parsed_kwargs.get("feature", "unknown"),
10
7
  "complexity": parsed_kwargs.get("complexity", "medium"),
@@ -14,23 +11,21 @@ def _create_architectural_assessment(args: str, parsed_kwargs: dict) -> dict:
14
11
 
15
12
  recommendations = []
16
13
 
17
- # Always recommend crackerjack-architect for planning
18
14
  recommendations.append(
19
15
  {
20
16
  "agent": "crackerjack-architect",
21
17
  "priority": "high",
22
18
  "reason": "Expert architectural planning for crackerjack compliance",
23
- "action": 'Task tool with subagent_type="crackerjack-architect" for feature planning and architecture',
19
+ "action": 'Task tool with subagent_type ="crackerjack-architect" for feature planning and architecture',
24
20
  "benefits": [
25
21
  "Prevents violations through proper initial architecture",
26
22
  "Applies crackerjack patterns from the start",
27
- "Reduces iteration cycles by 50%+",
23
+ "Reduces iteration cycles by 50 % +",
28
24
  "Ensures consistency with project standards",
29
25
  ],
30
26
  }
31
27
  )
32
28
 
33
- # Add complexity-specific recommendations
34
29
  complexity = parsed_kwargs.get("complexity", "medium")
35
30
  if complexity in ("high", "complex"):
36
31
  recommendations.append(
@@ -38,11 +33,10 @@ def _create_architectural_assessment(args: str, parsed_kwargs: dict) -> dict:
38
33
  "agent": "refactoring-specialist",
39
34
  "priority": "high",
40
35
  "reason": "Complex features require careful structural planning",
41
- "action": 'Task tool with subagent_type="refactoring-specialist" for complexity management',
36
+ "action": 'Task tool with subagent_type ="refactoring-specialist" for complexity management',
42
37
  }
43
38
  )
44
39
 
45
- # Add security recommendations for certain features
46
40
  feature = parsed_kwargs.get("feature", "")
47
41
  if any(
48
42
  keyword in feature.lower() for keyword in ("auth", "security", "api", "data")
@@ -52,7 +46,7 @@ def _create_architectural_assessment(args: str, parsed_kwargs: dict) -> dict:
52
46
  "agent": "security-auditor",
53
47
  "priority": "medium",
54
48
  "reason": "Security-sensitive feature requires expert review",
55
- "action": 'Task tool with subagent_type="security-auditor" for security validation',
49
+ "action": 'Task tool with subagent_type ="security-auditor" for security validation',
56
50
  }
57
51
  )
58
52
 
@@ -63,7 +57,6 @@ def _create_architectural_assessment(args: str, parsed_kwargs: dict) -> dict:
63
57
 
64
58
 
65
59
  def _create_validation_results(file_path: str) -> dict:
66
- """Create validation results for architectural compliance."""
67
60
  validation = {
68
61
  "file_path": file_path,
69
62
  "validation_results": [],
@@ -71,12 +64,11 @@ def _create_validation_results(file_path: str) -> dict:
71
64
  "recommendations": [],
72
65
  }
73
66
 
74
- # Check for crackerjack compliance patterns
75
67
  compliance_checks = [
76
68
  {
77
69
  "check": "complexity_compliance",
78
70
  "status": "requires_analysis",
79
- "message": "Cognitive complexity should be ≤13 per function",
71
+ "message": "Cognitive complexity should be ≤15 per function",
80
72
  "tool": "complexipy",
81
73
  },
82
74
  {
@@ -105,16 +97,15 @@ def _create_validation_results(file_path: str) -> dict:
105
97
 
106
98
  validation["validation_results"] = compliance_checks
107
99
 
108
- # Add proactive recommendations
109
100
  validation["recommendations"] = [
110
- "Run full crackerjack quality process: python -m crackerjack -t",
101
+ "Run full crackerjack quality process: python - m crackerjack-t",
111
102
  "Use crackerjack-architect for complex refactoring decisions",
112
103
  "Apply pattern learning from successful fixes",
113
104
  "Validate against architectural plan before committing",
114
105
  ]
115
106
 
116
107
  validation["next_steps"] = [
117
- 'Task tool with subagent_type="crackerjack-architect" for architectural guidance',
108
+ 'Task tool with subagent_type ="crackerjack-architect" for architectural guidance',
118
109
  "Run comprehensive quality checks",
119
110
  "Apply learned patterns from pattern cache",
120
111
  ]
@@ -123,7 +114,6 @@ def _create_validation_results(file_path: str) -> dict:
123
114
 
124
115
 
125
116
  def _create_pattern_suggestions(problem_context: str) -> dict:
126
- """Create pattern suggestions based on context."""
127
117
  pattern_suggestions = {
128
118
  "context": problem_context,
129
119
  "recommended_patterns": [],
@@ -131,32 +121,29 @@ def _create_pattern_suggestions(problem_context: str) -> dict:
131
121
  "specialist_agents": [],
132
122
  }
133
123
 
134
- # Add context-specific patterns
135
124
  _add_complexity_patterns(pattern_suggestions, problem_context)
136
125
  _add_dry_patterns(pattern_suggestions, problem_context)
137
126
  _add_performance_patterns(pattern_suggestions, problem_context)
138
127
  _add_security_patterns(pattern_suggestions, problem_context)
139
128
 
140
- # Add specialist agent recommendations
141
129
  pattern_suggestions["specialist_agents"] = [
142
130
  {
143
131
  "agent": "crackerjack-architect",
144
132
  "when_to_use": "For architectural decisions and complex pattern application",
145
- "action": 'Task tool with subagent_type="crackerjack-architect"',
133
+ "action": 'Task tool with subagent_type ="crackerjack-architect"',
146
134
  },
147
135
  {
148
136
  "agent": "refactoring-specialist",
149
137
  "when_to_use": "For complexity reduction and structural improvements",
150
- "action": 'Task tool with subagent_type="refactoring-specialist"',
138
+ "action": 'Task tool with subagent_type ="refactoring-specialist"',
151
139
  },
152
140
  {
153
141
  "agent": "security-auditor",
154
142
  "when_to_use": "For security pattern validation and vulnerability assessment",
155
- "action": 'Task tool with subagent_type="security-auditor"',
143
+ "action": 'Task tool with subagent_type ="security-auditor"',
156
144
  },
157
145
  ]
158
146
 
159
- # Implementation guidance
160
147
  pattern_suggestions["implementation_guidance"] = [
161
148
  "Start with crackerjack-architect for overall planning",
162
149
  "Apply one pattern at a time to avoid complexity",
@@ -165,7 +152,6 @@ def _create_pattern_suggestions(problem_context: str) -> dict:
165
152
  "Document architectural decisions for team knowledge",
166
153
  ]
167
154
 
168
- # Default patterns if none specified
169
155
  if not pattern_suggestions["recommended_patterns"]:
170
156
  pattern_suggestions["recommended_patterns"] = [
171
157
  {
@@ -183,7 +169,6 @@ def _create_pattern_suggestions(problem_context: str) -> dict:
183
169
 
184
170
 
185
171
  def _add_complexity_patterns(pattern_suggestions: dict, problem_context: str) -> None:
186
- """Add complexity-related patterns if relevant."""
187
172
  if any(
188
173
  keyword in problem_context.lower()
189
174
  for keyword in ("complex", "refactor", "cleanup")
@@ -213,7 +198,6 @@ def _add_complexity_patterns(pattern_suggestions: dict, problem_context: str) ->
213
198
 
214
199
 
215
200
  def _add_dry_patterns(pattern_suggestions: dict, problem_context: str) -> None:
216
- """Add DRY violation patterns if relevant."""
217
201
  if any(
218
202
  keyword in problem_context.lower() for keyword in ("duplicate", "repeat", "dry")
219
203
  ):
@@ -242,7 +226,6 @@ def _add_dry_patterns(pattern_suggestions: dict, problem_context: str) -> None:
242
226
 
243
227
 
244
228
  def _add_performance_patterns(pattern_suggestions: dict, problem_context: str) -> None:
245
- """Add performance patterns if relevant."""
246
229
  if any(
247
230
  keyword in problem_context.lower()
248
231
  for keyword in ("slow", "performance", "optimize")
@@ -272,7 +255,6 @@ def _add_performance_patterns(pattern_suggestions: dict, problem_context: str) -
272
255
 
273
256
 
274
257
  def _add_security_patterns(pattern_suggestions: dict, problem_context: str) -> None:
275
- """Add security patterns if relevant."""
276
258
  if any(
277
259
  keyword in problem_context.lower() for keyword in ("security", "safe", "secure")
278
260
  ):
@@ -301,7 +283,6 @@ def _add_security_patterns(pattern_suggestions: dict, problem_context: str) -> N
301
283
 
302
284
 
303
285
  def _create_error_response(error: Exception, recommendation: str) -> str:
304
- """Create standardized error response."""
305
286
  import json
306
287
 
307
288
  return json.dumps(
@@ -318,23 +299,18 @@ def _create_error_response(error: Exception, recommendation: str) -> str:
318
299
 
319
300
 
320
301
  def register_proactive_tools(mcp_app: t.Any) -> None:
321
- """Register proactive planning and execution tools."""
322
302
  return _register_proactive_tools(mcp_app)
323
303
 
324
304
 
325
305
  def _register_proactive_tools(mcp_app: t.Any) -> None:
326
- """Register proactive planning and execution tools."""
327
306
  _register_plan_development_tool(mcp_app)
328
307
  _register_validate_architecture_tool(mcp_app)
329
308
  _register_suggest_patterns_tool(mcp_app)
330
309
 
331
310
 
332
311
  def _register_plan_development_tool(mcp_app: t.Any) -> None:
333
- """Register the plan_development tool."""
334
-
335
312
  @mcp_app.tool()
336
313
  async def plan_development(args: str, kwargs: str) -> str:
337
- """Plan development approach using crackerjack-architect specialist."""
338
314
  import json
339
315
 
340
316
  try:
@@ -346,11 +322,8 @@ def _register_plan_development_tool(mcp_app: t.Any) -> None:
346
322
 
347
323
 
348
324
  def _register_validate_architecture_tool(mcp_app: t.Any) -> None:
349
- """Register the validate_architecture tool."""
350
-
351
325
  @mcp_app.tool()
352
326
  async def validate_architecture(args: str, kwargs: str) -> str:
353
- """Validate code against architectural patterns and crackerjack standards."""
354
327
  import json
355
328
 
356
329
  try:
@@ -360,16 +333,13 @@ def _register_validate_architecture_tool(mcp_app: t.Any) -> None:
360
333
  return json.dumps(validation, indent=2)
361
334
  except Exception as e:
362
335
  return _create_error_response(
363
- e, "Run standard crackerjack validation: python -m crackerjack"
336
+ e, "Run standard crackerjack validation: python-m crackerjack"
364
337
  )
365
338
 
366
339
 
367
340
  def _register_suggest_patterns_tool(mcp_app: t.Any) -> None:
368
- """Register the suggest_patterns tool."""
369
-
370
341
  @mcp_app.tool()
371
342
  async def suggest_patterns(args: str, kwargs: str) -> str:
372
- """Suggest crackerjack patterns for current development context."""
373
343
  import json
374
344
 
375
345
  try:
@@ -380,5 +350,5 @@ def _register_suggest_patterns_tool(mcp_app: t.Any) -> None:
380
350
  except Exception as e:
381
351
  return _create_error_response(
382
352
  e,
383
- 'Use Task tool with subagent_type="crackerjack-architect" for expert guidance',
353
+ 'Use Task tool with subagent_type ="crackerjack-architect" for expert guidance',
384
354
  )
@@ -4,25 +4,30 @@ import typing as t
4
4
  from pathlib import Path
5
5
 
6
6
  from crackerjack.mcp.context import get_context
7
+ from crackerjack.services.input_validator import get_input_validator
7
8
 
8
9
 
9
10
  def _create_progress_file(job_id: str) -> Path:
10
- import re
11
11
  import tempfile
12
12
 
13
- if not job_id or not isinstance(job_id, str):
14
- msg = f"Invalid job_id: {job_id}"
15
- raise ValueError(msg)
16
- if not re.match(r"^[a-zA-Z0-9_-]+$", job_id):
17
- msg = f"Invalid job_id format: {job_id}"
13
+ # Use secure input validation
14
+ job_id_result = get_input_validator().validate_job_id(job_id)
15
+
16
+ if not job_id_result.valid:
17
+ msg = f"Invalid job_id: {job_id_result.error_message}"
18
18
  raise ValueError(msg)
19
19
 
20
+ # Use sanitized job ID
21
+ sanitized_job_id = job_id_result.sanitized_value
22
+
20
23
  context = get_context()
21
24
  if context:
22
- return context.progress_dir / f"job-{job_id}.json"
25
+ return context.progress_dir / f"job-{sanitized_job_id}.json"
26
+
27
+ # Create secure temporary directory
23
28
  progress_dir = Path(tempfile.gettempdir()) / "crackerjack-mcp-progress"
24
- progress_dir.mkdir(exist_ok=True)
25
- return progress_dir / f"job-{job_id}.json"
29
+ progress_dir.mkdir(exist_ok=True, mode=0o750) # Restrictive permissions
30
+ return progress_dir / f"job-{sanitized_job_id}.json"
26
31
 
27
32
 
28
33
  def _clamp_progress(value: int) -> int:
@@ -96,7 +101,6 @@ def _update_progress(
96
101
  job_id: str,
97
102
  progress_data: dict[str, t.Any] | str = None,
98
103
  context: t.Any = None,
99
- # Legacy parameters for backward compatibility
100
104
  iteration: int = 1,
101
105
  max_iterations: int = 10,
102
106
  overall_progress: int = 0,
@@ -162,7 +166,7 @@ def _handle_get_job_progress(job_id: str) -> str:
162
166
  return f'{{"error": "Failed to get progress for job {job_id}: {e}"}}'
163
167
 
164
168
 
165
- def _execute_session_action(
169
+ async def _execute_session_action(
166
170
  state_manager,
167
171
  action: str,
168
172
  checkpoint_name: str | None,
@@ -174,7 +178,7 @@ def _execute_session_action(
174
178
 
175
179
  if action == "checkpoint":
176
180
  checkpoint_name = checkpoint_name or f"checkpoint_{context.get_current_time()}"
177
- state_manager.create_checkpoint(checkpoint_name)
181
+ await state_manager.save_checkpoint(checkpoint_name)
178
182
  return f'{{"status": "checkpoint_created", "action": "checkpoint", "name": "{checkpoint_name}"}}'
179
183
 
180
184
  if action == "complete":
@@ -188,7 +192,9 @@ def _execute_session_action(
188
192
  return f'{{"error": "Invalid action: {action}. Valid actions: start, checkpoint, complete, reset"}}'
189
193
 
190
194
 
191
- def _handle_session_management(action: str, checkpoint_name: str | None = None) -> str:
195
+ async def _handle_session_management(
196
+ action: str, checkpoint_name: str | None = None
197
+ ) -> str:
192
198
  context = get_context()
193
199
  if not context:
194
200
  return '{"error": "Server context not available"}'
@@ -198,7 +204,9 @@ def _handle_session_management(action: str, checkpoint_name: str | None = None)
198
204
  if not state_manager:
199
205
  return '{"error": "State manager not available"}'
200
206
 
201
- return _execute_session_action(state_manager, action, checkpoint_name, context)
207
+ return await _execute_session_action(
208
+ state_manager, action, checkpoint_name, context
209
+ )
202
210
 
203
211
  except Exception as e:
204
212
  return f'{{"error": "Session management failed: {e}"}}'
@@ -214,4 +222,4 @@ def register_progress_tools(mcp_app: t.Any) -> None:
214
222
  action: str,
215
223
  checkpoint_name: str | None = None,
216
224
  ) -> str:
217
- return _handle_session_management(action, checkpoint_name)
225
+ return await _handle_session_management(action, checkpoint_name)
@@ -8,12 +8,10 @@ from crackerjack.mcp.context import get_context
8
8
 
9
9
 
10
10
  def _create_error_response(message: str, success: bool = False) -> str:
11
- """Utility function to create standardized error responses."""
12
11
  return json.dumps({"error": message, "success": success}, indent=2)
13
12
 
14
13
 
15
14
  def register_utility_tools(mcp_app: t.Any) -> None:
16
- """Register utility slash command tools."""
17
15
  _register_clean_tool(mcp_app)
18
16
  _register_config_tool(mcp_app)
19
17
  _register_analyze_tool(mcp_app)
@@ -22,7 +20,6 @@ def register_utility_tools(mcp_app: t.Any) -> None:
22
20
  def _clean_file_if_old(
23
21
  file_path: Path, cutoff_time: float, dry_run: bool, file_type: str
24
22
  ) -> dict | None:
25
- """Clean a single file if it's older than cutoff time."""
26
23
  with suppress(OSError):
27
24
  if file_path.stat().st_mtime < cutoff_time:
28
25
  file_size = file_path.stat().st_size
@@ -33,14 +30,13 @@ def _clean_file_if_old(
33
30
 
34
31
 
35
32
  def _clean_temp_files(cutoff_time: float, dry_run: bool) -> tuple[list[dict], int]:
36
- """Clean temporary files older than cutoff time."""
37
33
  import tempfile
38
34
 
39
35
  cleaned_files = []
40
36
  total_size = 0
41
37
  temp_dir = Path(tempfile.gettempdir())
42
38
 
43
- patterns = ("crackerjack-*.log", "crackerjack-task-error-*.log", ".coverage.*")
39
+ patterns = ("crackerjack-*.log", "crackerjack - task - error-*.log", ".coverage.*")
44
40
  for pattern in patterns:
45
41
  for file_path in temp_dir.glob(pattern):
46
42
  file_info = _clean_file_if_old(file_path, cutoff_time, dry_run, "temp")
@@ -54,7 +50,6 @@ def _clean_temp_files(cutoff_time: float, dry_run: bool) -> tuple[list[dict], in
54
50
  def _clean_progress_files(
55
51
  context: t.Any, cutoff_time: float, dry_run: bool
56
52
  ) -> tuple[list[dict], int]:
57
- """Clean progress files older than cutoff time."""
58
53
  cleaned_files = []
59
54
  total_size = 0
60
55
 
@@ -71,7 +66,6 @@ def _clean_progress_files(
71
66
 
72
67
 
73
68
  def _parse_cleanup_options(kwargs: str) -> tuple[dict, str | None]:
74
- """Parse and validate cleanup options from kwargs string."""
75
69
  try:
76
70
  extra_kwargs = json.loads(kwargs) if kwargs.strip() else {}
77
71
  return extra_kwargs, None
@@ -82,12 +76,6 @@ def _parse_cleanup_options(kwargs: str) -> tuple[dict, str | None]:
82
76
  def _register_clean_tool(mcp_app: t.Any) -> None:
83
77
  @mcp_app.tool()
84
78
  async def clean_crackerjack(args: str = "", kwargs: str = "{}") -> str:
85
- """Clean up temporary files, stale progress data, and cached resources.
86
-
87
- Args:
88
- args: Optional cleanup scope: 'temp', 'progress', 'cache', 'all' (default)
89
- kwargs: JSON with options like {"dry_run": true, "older_than": 24}
90
- """
91
79
  context = get_context()
92
80
  if not context:
93
81
  return _create_error_response("Server context not available")
@@ -104,7 +92,6 @@ def _register_clean_tool(mcp_app: t.Any) -> None:
104
92
 
105
93
 
106
94
  def _parse_clean_configuration(args: str, kwargs: str) -> dict:
107
- """Parse and validate cleanup configuration from arguments."""
108
95
  extra_kwargs, parse_error = _parse_cleanup_options(kwargs)
109
96
  if parse_error:
110
97
  return {"error": parse_error}
@@ -117,7 +104,6 @@ def _parse_clean_configuration(args: str, kwargs: str) -> dict:
117
104
 
118
105
 
119
106
  def _execute_cleanup_operations(context: t.Any, clean_config: dict) -> dict:
120
- """Execute the cleanup operations based on configuration."""
121
107
  from datetime import datetime, timedelta
122
108
 
123
109
  cutoff_time = (
@@ -126,13 +112,11 @@ def _execute_cleanup_operations(context: t.Any, clean_config: dict) -> dict:
126
112
  all_cleaned_files = []
127
113
  total_size = 0
128
114
 
129
- # Clean temp files
130
115
  if clean_config["scope"] in ("temp", "all"):
131
116
  temp_files, temp_size = _clean_temp_files(cutoff_time, clean_config["dry_run"])
132
117
  all_cleaned_files.extend(temp_files)
133
118
  total_size += temp_size
134
119
 
135
- # Clean progress files
136
120
  if clean_config["scope"] in ("progress", "all"):
137
121
  progress_files, progress_size = _clean_progress_files(
138
122
  context, cutoff_time, clean_config["dry_run"]
@@ -140,16 +124,13 @@ def _execute_cleanup_operations(context: t.Any, clean_config: dict) -> dict:
140
124
  all_cleaned_files.extend(progress_files)
141
125
  total_size += progress_size
142
126
 
143
- # Clean cache files (if any caching is implemented)
144
127
  if clean_config["scope"] in ("cache", "all"):
145
- # Placeholder for future cache cleaning
146
128
  pass
147
129
 
148
130
  return {"all_cleaned_files": all_cleaned_files, "total_size": total_size}
149
131
 
150
132
 
151
133
  def _create_cleanup_response(clean_config: dict, cleanup_results: dict) -> str:
152
- """Create the cleanup response JSON."""
153
134
  all_cleaned_files = cleanup_results["all_cleaned_files"]
154
135
 
155
136
  return json.dumps(
@@ -170,7 +151,6 @@ def _create_cleanup_response(clean_config: dict, cleanup_results: dict) -> str:
170
151
 
171
152
 
172
153
  def _handle_config_list(context: t.Any) -> dict[str, t.Any]:
173
- """Handle config list action."""
174
154
  return {
175
155
  "project_path": str(context.config.project_path),
176
156
  "rate_limiter": {
@@ -185,7 +165,6 @@ def _handle_config_list(context: t.Any) -> dict[str, t.Any]:
185
165
 
186
166
 
187
167
  def _handle_config_get(context: t.Any, key: str) -> dict[str, t.Any]:
188
- """Handle config get action."""
189
168
  value = getattr(context.config, key, None)
190
169
  if value is None:
191
170
  value = getattr(context, key, "Key not found")
@@ -200,7 +179,6 @@ def _handle_config_get(context: t.Any, key: str) -> dict[str, t.Any]:
200
179
 
201
180
 
202
181
  def _handle_config_validate(context: t.Any) -> dict[str, t.Any]:
203
- """Handle config validate action."""
204
182
  validation_results = {
205
183
  "project_path_exists": context.config.project_path.exists(),
206
184
  "progress_dir_writable": context.progress_dir.exists()
@@ -222,12 +200,6 @@ def _handle_config_validate(context: t.Any) -> dict[str, t.Any]:
222
200
  def _register_config_tool(mcp_app: t.Any) -> None:
223
201
  @mcp_app.tool()
224
202
  async def config_crackerjack(args: str = "", kwargs: str = "{}") -> str:
225
- """View or update crackerjack configuration.
226
-
227
- Args:
228
- args: Action - 'get <key>', 'set <key=value>', 'list', or 'validate'
229
- kwargs: JSON with additional options
230
- """
231
203
  context = get_context()
232
204
  if not context:
233
205
  return _create_error_response("Server context not available")
@@ -254,7 +226,7 @@ def _register_config_tool(mcp_app: t.Any) -> None:
254
226
  result = _handle_config_validate(context)
255
227
  else:
256
228
  return _create_error_response(
257
- f"Invalid action '{action}'. Valid actions: list, get <key>, validate"
229
+ f"Invalid action '{action}'. Valid actions: list, get < key >, validate"
258
230
  )
259
231
 
260
232
  return json.dumps(result, indent=2)
@@ -264,7 +236,6 @@ def _register_config_tool(mcp_app: t.Any) -> None:
264
236
 
265
237
 
266
238
  def _run_hooks_analysis(orchestrator: t.Any, options: t.Any) -> dict:
267
- """Run hooks analysis and return results."""
268
239
  fast_result = orchestrator.run_fast_hooks_only(options)
269
240
  comprehensive_result = orchestrator.run_comprehensive_hooks_only(options)
270
241
 
@@ -275,31 +246,23 @@ def _run_hooks_analysis(orchestrator: t.Any, options: t.Any) -> dict:
275
246
 
276
247
 
277
248
  def _run_tests_analysis(orchestrator: t.Any, options: t.Any) -> dict:
278
- """Run tests analysis and return results."""
279
249
  test_result = orchestrator.run_testing_phase(options)
280
250
  return {"status": "passed" if test_result else "failed"}
281
251
 
282
252
 
283
253
  def _create_analysis_orchestrator(context: t.Any) -> t.Any:
284
- """Create workflow orchestrator for analysis."""
285
254
  from crackerjack.core.workflow_orchestrator import WorkflowOrchestrator
286
255
 
287
256
  return WorkflowOrchestrator(
288
257
  console=context.console,
289
258
  pkg_path=context.config.project_path,
290
- dry_run=True, # Analysis only, no changes
259
+ dry_run=True,
291
260
  )
292
261
 
293
262
 
294
263
  def _register_analyze_tool(mcp_app: t.Any) -> None:
295
264
  @mcp_app.tool()
296
265
  async def analyze_crackerjack(args: str = "", kwargs: str = "{}") -> str:
297
- """Analyze code quality without making changes.
298
-
299
- Args:
300
- args: Analysis scope - 'hooks', 'tests', 'all' (default)
301
- kwargs: JSON with options like {"report_format": "summary"}
302
- """
303
266
  context = get_context()
304
267
  if not context:
305
268
  return _create_error_response("Server context not available")