crackerjack 0.18.2__py3-none-any.whl → 0.45.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (533) hide show
  1. crackerjack/README.md +19 -0
  2. crackerjack/__init__.py +96 -2
  3. crackerjack/__main__.py +637 -138
  4. crackerjack/adapters/README.md +18 -0
  5. crackerjack/adapters/__init__.py +39 -0
  6. crackerjack/adapters/_output_paths.py +167 -0
  7. crackerjack/adapters/_qa_adapter_base.py +309 -0
  8. crackerjack/adapters/_tool_adapter_base.py +706 -0
  9. crackerjack/adapters/ai/README.md +65 -0
  10. crackerjack/adapters/ai/__init__.py +5 -0
  11. crackerjack/adapters/ai/claude.py +853 -0
  12. crackerjack/adapters/complexity/README.md +53 -0
  13. crackerjack/adapters/complexity/__init__.py +10 -0
  14. crackerjack/adapters/complexity/complexipy.py +641 -0
  15. crackerjack/adapters/dependency/__init__.py +22 -0
  16. crackerjack/adapters/dependency/pip_audit.py +418 -0
  17. crackerjack/adapters/format/README.md +72 -0
  18. crackerjack/adapters/format/__init__.py +11 -0
  19. crackerjack/adapters/format/mdformat.py +313 -0
  20. crackerjack/adapters/format/ruff.py +516 -0
  21. crackerjack/adapters/lint/README.md +47 -0
  22. crackerjack/adapters/lint/__init__.py +11 -0
  23. crackerjack/adapters/lint/codespell.py +273 -0
  24. crackerjack/adapters/lsp/README.md +49 -0
  25. crackerjack/adapters/lsp/__init__.py +27 -0
  26. crackerjack/adapters/lsp/_base.py +194 -0
  27. crackerjack/adapters/lsp/_client.py +358 -0
  28. crackerjack/adapters/lsp/_manager.py +193 -0
  29. crackerjack/adapters/lsp/skylos.py +283 -0
  30. crackerjack/adapters/lsp/zuban.py +557 -0
  31. crackerjack/adapters/refactor/README.md +59 -0
  32. crackerjack/adapters/refactor/__init__.py +12 -0
  33. crackerjack/adapters/refactor/creosote.py +318 -0
  34. crackerjack/adapters/refactor/refurb.py +406 -0
  35. crackerjack/adapters/refactor/skylos.py +494 -0
  36. crackerjack/adapters/sast/README.md +132 -0
  37. crackerjack/adapters/sast/__init__.py +32 -0
  38. crackerjack/adapters/sast/_base.py +201 -0
  39. crackerjack/adapters/sast/bandit.py +423 -0
  40. crackerjack/adapters/sast/pyscn.py +405 -0
  41. crackerjack/adapters/sast/semgrep.py +241 -0
  42. crackerjack/adapters/security/README.md +111 -0
  43. crackerjack/adapters/security/__init__.py +17 -0
  44. crackerjack/adapters/security/gitleaks.py +339 -0
  45. crackerjack/adapters/type/README.md +52 -0
  46. crackerjack/adapters/type/__init__.py +12 -0
  47. crackerjack/adapters/type/pyrefly.py +402 -0
  48. crackerjack/adapters/type/ty.py +402 -0
  49. crackerjack/adapters/type/zuban.py +522 -0
  50. crackerjack/adapters/utility/README.md +51 -0
  51. crackerjack/adapters/utility/__init__.py +10 -0
  52. crackerjack/adapters/utility/checks.py +884 -0
  53. crackerjack/agents/README.md +264 -0
  54. crackerjack/agents/__init__.py +66 -0
  55. crackerjack/agents/architect_agent.py +238 -0
  56. crackerjack/agents/base.py +167 -0
  57. crackerjack/agents/claude_code_bridge.py +641 -0
  58. crackerjack/agents/coordinator.py +600 -0
  59. crackerjack/agents/documentation_agent.py +520 -0
  60. crackerjack/agents/dry_agent.py +585 -0
  61. crackerjack/agents/enhanced_coordinator.py +279 -0
  62. crackerjack/agents/enhanced_proactive_agent.py +185 -0
  63. crackerjack/agents/error_middleware.py +53 -0
  64. crackerjack/agents/formatting_agent.py +230 -0
  65. crackerjack/agents/helpers/__init__.py +9 -0
  66. crackerjack/agents/helpers/performance/__init__.py +22 -0
  67. crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
  68. crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
  69. crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
  70. crackerjack/agents/helpers/refactoring/__init__.py +22 -0
  71. crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
  72. crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
  73. crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
  74. crackerjack/agents/helpers/test_creation/__init__.py +19 -0
  75. crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
  76. crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
  77. crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
  78. crackerjack/agents/import_optimization_agent.py +1181 -0
  79. crackerjack/agents/performance_agent.py +325 -0
  80. crackerjack/agents/performance_helpers.py +205 -0
  81. crackerjack/agents/proactive_agent.py +55 -0
  82. crackerjack/agents/refactoring_agent.py +511 -0
  83. crackerjack/agents/refactoring_helpers.py +247 -0
  84. crackerjack/agents/security_agent.py +793 -0
  85. crackerjack/agents/semantic_agent.py +479 -0
  86. crackerjack/agents/semantic_helpers.py +356 -0
  87. crackerjack/agents/test_creation_agent.py +570 -0
  88. crackerjack/agents/test_specialist_agent.py +526 -0
  89. crackerjack/agents/tracker.py +110 -0
  90. crackerjack/api.py +647 -0
  91. crackerjack/cli/README.md +394 -0
  92. crackerjack/cli/__init__.py +24 -0
  93. crackerjack/cli/cache_handlers.py +209 -0
  94. crackerjack/cli/cache_handlers_enhanced.py +680 -0
  95. crackerjack/cli/facade.py +162 -0
  96. crackerjack/cli/formatting.py +13 -0
  97. crackerjack/cli/handlers/__init__.py +85 -0
  98. crackerjack/cli/handlers/advanced.py +103 -0
  99. crackerjack/cli/handlers/ai_features.py +62 -0
  100. crackerjack/cli/handlers/analytics.py +479 -0
  101. crackerjack/cli/handlers/changelog.py +271 -0
  102. crackerjack/cli/handlers/config_handlers.py +16 -0
  103. crackerjack/cli/handlers/coverage.py +84 -0
  104. crackerjack/cli/handlers/documentation.py +280 -0
  105. crackerjack/cli/handlers/main_handlers.py +497 -0
  106. crackerjack/cli/handlers/monitoring.py +371 -0
  107. crackerjack/cli/handlers.py +700 -0
  108. crackerjack/cli/interactive.py +488 -0
  109. crackerjack/cli/options.py +1216 -0
  110. crackerjack/cli/semantic_handlers.py +292 -0
  111. crackerjack/cli/utils.py +19 -0
  112. crackerjack/cli/version.py +19 -0
  113. crackerjack/code_cleaner.py +1307 -0
  114. crackerjack/config/README.md +472 -0
  115. crackerjack/config/__init__.py +275 -0
  116. crackerjack/config/global_lock_config.py +207 -0
  117. crackerjack/config/hooks.py +390 -0
  118. crackerjack/config/loader.py +239 -0
  119. crackerjack/config/settings.py +141 -0
  120. crackerjack/config/tool_commands.py +331 -0
  121. crackerjack/core/README.md +393 -0
  122. crackerjack/core/__init__.py +0 -0
  123. crackerjack/core/async_workflow_orchestrator.py +738 -0
  124. crackerjack/core/autofix_coordinator.py +282 -0
  125. crackerjack/core/container.py +105 -0
  126. crackerjack/core/enhanced_container.py +583 -0
  127. crackerjack/core/file_lifecycle.py +472 -0
  128. crackerjack/core/performance.py +244 -0
  129. crackerjack/core/performance_monitor.py +357 -0
  130. crackerjack/core/phase_coordinator.py +1227 -0
  131. crackerjack/core/proactive_workflow.py +267 -0
  132. crackerjack/core/resource_manager.py +425 -0
  133. crackerjack/core/retry.py +275 -0
  134. crackerjack/core/service_watchdog.py +601 -0
  135. crackerjack/core/session_coordinator.py +239 -0
  136. crackerjack/core/timeout_manager.py +563 -0
  137. crackerjack/core/websocket_lifecycle.py +410 -0
  138. crackerjack/core/workflow/__init__.py +21 -0
  139. crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
  140. crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
  141. crackerjack/core/workflow/workflow_issue_parser.py +714 -0
  142. crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
  143. crackerjack/core/workflow/workflow_security_gates.py +400 -0
  144. crackerjack/core/workflow_orchestrator.py +2243 -0
  145. crackerjack/data/README.md +11 -0
  146. crackerjack/data/__init__.py +8 -0
  147. crackerjack/data/models.py +79 -0
  148. crackerjack/data/repository.py +210 -0
  149. crackerjack/decorators/README.md +180 -0
  150. crackerjack/decorators/__init__.py +35 -0
  151. crackerjack/decorators/error_handling.py +649 -0
  152. crackerjack/decorators/error_handling_decorators.py +334 -0
  153. crackerjack/decorators/helpers.py +58 -0
  154. crackerjack/decorators/patterns.py +281 -0
  155. crackerjack/decorators/utils.py +58 -0
  156. crackerjack/docs/INDEX.md +11 -0
  157. crackerjack/docs/README.md +11 -0
  158. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  159. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  160. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  161. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  162. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  163. crackerjack/documentation/README.md +11 -0
  164. crackerjack/documentation/__init__.py +31 -0
  165. crackerjack/documentation/ai_templates.py +756 -0
  166. crackerjack/documentation/dual_output_generator.py +767 -0
  167. crackerjack/documentation/mkdocs_integration.py +518 -0
  168. crackerjack/documentation/reference_generator.py +1065 -0
  169. crackerjack/dynamic_config.py +678 -0
  170. crackerjack/errors.py +378 -0
  171. crackerjack/events/README.md +11 -0
  172. crackerjack/events/__init__.py +16 -0
  173. crackerjack/events/telemetry.py +175 -0
  174. crackerjack/events/workflow_bus.py +346 -0
  175. crackerjack/exceptions/README.md +301 -0
  176. crackerjack/exceptions/__init__.py +5 -0
  177. crackerjack/exceptions/config.py +4 -0
  178. crackerjack/exceptions/tool_execution_error.py +245 -0
  179. crackerjack/executors/README.md +591 -0
  180. crackerjack/executors/__init__.py +13 -0
  181. crackerjack/executors/async_hook_executor.py +938 -0
  182. crackerjack/executors/cached_hook_executor.py +316 -0
  183. crackerjack/executors/hook_executor.py +1295 -0
  184. crackerjack/executors/hook_lock_manager.py +708 -0
  185. crackerjack/executors/individual_hook_executor.py +739 -0
  186. crackerjack/executors/lsp_aware_hook_executor.py +349 -0
  187. crackerjack/executors/progress_hook_executor.py +282 -0
  188. crackerjack/executors/tool_proxy.py +433 -0
  189. crackerjack/hooks/README.md +485 -0
  190. crackerjack/hooks/lsp_hook.py +93 -0
  191. crackerjack/intelligence/README.md +557 -0
  192. crackerjack/intelligence/__init__.py +37 -0
  193. crackerjack/intelligence/adaptive_learning.py +693 -0
  194. crackerjack/intelligence/agent_orchestrator.py +485 -0
  195. crackerjack/intelligence/agent_registry.py +377 -0
  196. crackerjack/intelligence/agent_selector.py +439 -0
  197. crackerjack/intelligence/integration.py +250 -0
  198. crackerjack/interactive.py +719 -0
  199. crackerjack/managers/README.md +369 -0
  200. crackerjack/managers/__init__.py +11 -0
  201. crackerjack/managers/async_hook_manager.py +135 -0
  202. crackerjack/managers/hook_manager.py +585 -0
  203. crackerjack/managers/publish_manager.py +631 -0
  204. crackerjack/managers/test_command_builder.py +391 -0
  205. crackerjack/managers/test_executor.py +474 -0
  206. crackerjack/managers/test_manager.py +1357 -0
  207. crackerjack/managers/test_progress.py +187 -0
  208. crackerjack/mcp/README.md +374 -0
  209. crackerjack/mcp/__init__.py +0 -0
  210. crackerjack/mcp/cache.py +352 -0
  211. crackerjack/mcp/client_runner.py +121 -0
  212. crackerjack/mcp/context.py +802 -0
  213. crackerjack/mcp/dashboard.py +657 -0
  214. crackerjack/mcp/enhanced_progress_monitor.py +493 -0
  215. crackerjack/mcp/file_monitor.py +394 -0
  216. crackerjack/mcp/progress_components.py +607 -0
  217. crackerjack/mcp/progress_monitor.py +1016 -0
  218. crackerjack/mcp/rate_limiter.py +336 -0
  219. crackerjack/mcp/server.py +24 -0
  220. crackerjack/mcp/server_core.py +526 -0
  221. crackerjack/mcp/service_watchdog.py +505 -0
  222. crackerjack/mcp/state.py +407 -0
  223. crackerjack/mcp/task_manager.py +259 -0
  224. crackerjack/mcp/tools/README.md +27 -0
  225. crackerjack/mcp/tools/__init__.py +19 -0
  226. crackerjack/mcp/tools/core_tools.py +469 -0
  227. crackerjack/mcp/tools/error_analyzer.py +283 -0
  228. crackerjack/mcp/tools/execution_tools.py +384 -0
  229. crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
  230. crackerjack/mcp/tools/intelligence_tools.py +264 -0
  231. crackerjack/mcp/tools/monitoring_tools.py +628 -0
  232. crackerjack/mcp/tools/proactive_tools.py +367 -0
  233. crackerjack/mcp/tools/progress_tools.py +222 -0
  234. crackerjack/mcp/tools/semantic_tools.py +584 -0
  235. crackerjack/mcp/tools/utility_tools.py +358 -0
  236. crackerjack/mcp/tools/workflow_executor.py +699 -0
  237. crackerjack/mcp/websocket/README.md +31 -0
  238. crackerjack/mcp/websocket/__init__.py +14 -0
  239. crackerjack/mcp/websocket/app.py +54 -0
  240. crackerjack/mcp/websocket/endpoints.py +492 -0
  241. crackerjack/mcp/websocket/event_bridge.py +188 -0
  242. crackerjack/mcp/websocket/jobs.py +406 -0
  243. crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
  244. crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
  245. crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
  246. crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
  247. crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
  248. crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
  249. crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
  250. crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
  251. crackerjack/mcp/websocket/monitoring/factory.py +109 -0
  252. crackerjack/mcp/websocket/monitoring/filters.py +10 -0
  253. crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
  254. crackerjack/mcp/websocket/monitoring/models.py +90 -0
  255. crackerjack/mcp/websocket/monitoring/utils.py +171 -0
  256. crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
  257. crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
  258. crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
  259. crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
  260. crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
  261. crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
  262. crackerjack/mcp/websocket/monitoring_endpoints.py +21 -0
  263. crackerjack/mcp/websocket/server.py +174 -0
  264. crackerjack/mcp/websocket/websocket_handler.py +276 -0
  265. crackerjack/mcp/websocket_server.py +10 -0
  266. crackerjack/models/README.md +308 -0
  267. crackerjack/models/__init__.py +40 -0
  268. crackerjack/models/config.py +730 -0
  269. crackerjack/models/config_adapter.py +265 -0
  270. crackerjack/models/protocols.py +1535 -0
  271. crackerjack/models/pydantic_models.py +320 -0
  272. crackerjack/models/qa_config.py +145 -0
  273. crackerjack/models/qa_results.py +134 -0
  274. crackerjack/models/resource_protocols.py +299 -0
  275. crackerjack/models/results.py +35 -0
  276. crackerjack/models/semantic_models.py +258 -0
  277. crackerjack/models/task.py +173 -0
  278. crackerjack/models/test_models.py +60 -0
  279. crackerjack/monitoring/README.md +11 -0
  280. crackerjack/monitoring/__init__.py +0 -0
  281. crackerjack/monitoring/ai_agent_watchdog.py +405 -0
  282. crackerjack/monitoring/metrics_collector.py +427 -0
  283. crackerjack/monitoring/regression_prevention.py +580 -0
  284. crackerjack/monitoring/websocket_server.py +406 -0
  285. crackerjack/orchestration/README.md +340 -0
  286. crackerjack/orchestration/__init__.py +43 -0
  287. crackerjack/orchestration/advanced_orchestrator.py +894 -0
  288. crackerjack/orchestration/cache/README.md +312 -0
  289. crackerjack/orchestration/cache/__init__.py +37 -0
  290. crackerjack/orchestration/cache/memory_cache.py +338 -0
  291. crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
  292. crackerjack/orchestration/config.py +297 -0
  293. crackerjack/orchestration/coverage_improvement.py +180 -0
  294. crackerjack/orchestration/execution_strategies.py +361 -0
  295. crackerjack/orchestration/hook_orchestrator.py +1398 -0
  296. crackerjack/orchestration/strategies/README.md +401 -0
  297. crackerjack/orchestration/strategies/__init__.py +39 -0
  298. crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
  299. crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
  300. crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
  301. crackerjack/orchestration/test_progress_streamer.py +647 -0
  302. crackerjack/plugins/README.md +11 -0
  303. crackerjack/plugins/__init__.py +15 -0
  304. crackerjack/plugins/base.py +200 -0
  305. crackerjack/plugins/hooks.py +254 -0
  306. crackerjack/plugins/loader.py +335 -0
  307. crackerjack/plugins/managers.py +264 -0
  308. crackerjack/py313.py +191 -0
  309. crackerjack/security/README.md +11 -0
  310. crackerjack/security/__init__.py +0 -0
  311. crackerjack/security/audit.py +197 -0
  312. crackerjack/services/README.md +374 -0
  313. crackerjack/services/__init__.py +9 -0
  314. crackerjack/services/ai/README.md +295 -0
  315. crackerjack/services/ai/__init__.py +7 -0
  316. crackerjack/services/ai/advanced_optimizer.py +878 -0
  317. crackerjack/services/ai/contextual_ai_assistant.py +542 -0
  318. crackerjack/services/ai/embeddings.py +444 -0
  319. crackerjack/services/ai/intelligent_commit.py +328 -0
  320. crackerjack/services/ai/predictive_analytics.py +510 -0
  321. crackerjack/services/anomaly_detector.py +392 -0
  322. crackerjack/services/api_extractor.py +617 -0
  323. crackerjack/services/backup_service.py +467 -0
  324. crackerjack/services/bounded_status_operations.py +530 -0
  325. crackerjack/services/cache.py +369 -0
  326. crackerjack/services/changelog_automation.py +399 -0
  327. crackerjack/services/command_execution_service.py +305 -0
  328. crackerjack/services/config_integrity.py +132 -0
  329. crackerjack/services/config_merge.py +546 -0
  330. crackerjack/services/config_service.py +198 -0
  331. crackerjack/services/config_template.py +493 -0
  332. crackerjack/services/coverage_badge_service.py +173 -0
  333. crackerjack/services/coverage_ratchet.py +381 -0
  334. crackerjack/services/debug.py +733 -0
  335. crackerjack/services/dependency_analyzer.py +460 -0
  336. crackerjack/services/dependency_monitor.py +622 -0
  337. crackerjack/services/documentation_generator.py +493 -0
  338. crackerjack/services/documentation_service.py +704 -0
  339. crackerjack/services/enhanced_filesystem.py +497 -0
  340. crackerjack/services/enterprise_optimizer.py +865 -0
  341. crackerjack/services/error_pattern_analyzer.py +676 -0
  342. crackerjack/services/file_filter.py +221 -0
  343. crackerjack/services/file_hasher.py +149 -0
  344. crackerjack/services/file_io_service.py +361 -0
  345. crackerjack/services/file_modifier.py +615 -0
  346. crackerjack/services/filesystem.py +381 -0
  347. crackerjack/services/git.py +422 -0
  348. crackerjack/services/health_metrics.py +615 -0
  349. crackerjack/services/heatmap_generator.py +744 -0
  350. crackerjack/services/incremental_executor.py +380 -0
  351. crackerjack/services/initialization.py +823 -0
  352. crackerjack/services/input_validator.py +668 -0
  353. crackerjack/services/intelligent_commit.py +327 -0
  354. crackerjack/services/log_manager.py +289 -0
  355. crackerjack/services/logging.py +228 -0
  356. crackerjack/services/lsp_client.py +628 -0
  357. crackerjack/services/memory_optimizer.py +414 -0
  358. crackerjack/services/metrics.py +587 -0
  359. crackerjack/services/monitoring/README.md +30 -0
  360. crackerjack/services/monitoring/__init__.py +9 -0
  361. crackerjack/services/monitoring/dependency_monitor.py +678 -0
  362. crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
  363. crackerjack/services/monitoring/health_metrics.py +716 -0
  364. crackerjack/services/monitoring/metrics.py +587 -0
  365. crackerjack/services/monitoring/performance_benchmarks.py +410 -0
  366. crackerjack/services/monitoring/performance_cache.py +388 -0
  367. crackerjack/services/monitoring/performance_monitor.py +569 -0
  368. crackerjack/services/parallel_executor.py +527 -0
  369. crackerjack/services/pattern_cache.py +333 -0
  370. crackerjack/services/pattern_detector.py +478 -0
  371. crackerjack/services/patterns/__init__.py +142 -0
  372. crackerjack/services/patterns/agents.py +107 -0
  373. crackerjack/services/patterns/code/__init__.py +15 -0
  374. crackerjack/services/patterns/code/detection.py +118 -0
  375. crackerjack/services/patterns/code/imports.py +107 -0
  376. crackerjack/services/patterns/code/paths.py +159 -0
  377. crackerjack/services/patterns/code/performance.py +119 -0
  378. crackerjack/services/patterns/code/replacement.py +36 -0
  379. crackerjack/services/patterns/core.py +212 -0
  380. crackerjack/services/patterns/documentation/__init__.py +14 -0
  381. crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
  382. crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
  383. crackerjack/services/patterns/documentation/docstrings.py +89 -0
  384. crackerjack/services/patterns/formatting.py +226 -0
  385. crackerjack/services/patterns/operations.py +339 -0
  386. crackerjack/services/patterns/security/__init__.py +23 -0
  387. crackerjack/services/patterns/security/code_injection.py +122 -0
  388. crackerjack/services/patterns/security/credentials.py +190 -0
  389. crackerjack/services/patterns/security/path_traversal.py +221 -0
  390. crackerjack/services/patterns/security/unsafe_operations.py +216 -0
  391. crackerjack/services/patterns/templates.py +62 -0
  392. crackerjack/services/patterns/testing/__init__.py +18 -0
  393. crackerjack/services/patterns/testing/error_patterns.py +107 -0
  394. crackerjack/services/patterns/testing/pytest_output.py +126 -0
  395. crackerjack/services/patterns/tool_output/__init__.py +16 -0
  396. crackerjack/services/patterns/tool_output/bandit.py +72 -0
  397. crackerjack/services/patterns/tool_output/other.py +97 -0
  398. crackerjack/services/patterns/tool_output/pyright.py +67 -0
  399. crackerjack/services/patterns/tool_output/ruff.py +44 -0
  400. crackerjack/services/patterns/url_sanitization.py +114 -0
  401. crackerjack/services/patterns/utilities.py +42 -0
  402. crackerjack/services/patterns/utils.py +339 -0
  403. crackerjack/services/patterns/validation.py +46 -0
  404. crackerjack/services/patterns/versioning.py +62 -0
  405. crackerjack/services/predictive_analytics.py +523 -0
  406. crackerjack/services/profiler.py +280 -0
  407. crackerjack/services/quality/README.md +415 -0
  408. crackerjack/services/quality/__init__.py +11 -0
  409. crackerjack/services/quality/anomaly_detector.py +392 -0
  410. crackerjack/services/quality/pattern_cache.py +333 -0
  411. crackerjack/services/quality/pattern_detector.py +479 -0
  412. crackerjack/services/quality/qa_orchestrator.py +491 -0
  413. crackerjack/services/quality/quality_baseline.py +395 -0
  414. crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
  415. crackerjack/services/quality/quality_intelligence.py +949 -0
  416. crackerjack/services/regex_patterns.py +58 -0
  417. crackerjack/services/regex_utils.py +483 -0
  418. crackerjack/services/secure_path_utils.py +524 -0
  419. crackerjack/services/secure_status_formatter.py +450 -0
  420. crackerjack/services/secure_subprocess.py +635 -0
  421. crackerjack/services/security.py +239 -0
  422. crackerjack/services/security_logger.py +495 -0
  423. crackerjack/services/server_manager.py +411 -0
  424. crackerjack/services/smart_scheduling.py +167 -0
  425. crackerjack/services/status_authentication.py +460 -0
  426. crackerjack/services/status_security_manager.py +315 -0
  427. crackerjack/services/terminal_utils.py +0 -0
  428. crackerjack/services/thread_safe_status_collector.py +441 -0
  429. crackerjack/services/tool_filter.py +368 -0
  430. crackerjack/services/tool_version_service.py +43 -0
  431. crackerjack/services/unified_config.py +115 -0
  432. crackerjack/services/validation_rate_limiter.py +220 -0
  433. crackerjack/services/vector_store.py +689 -0
  434. crackerjack/services/version_analyzer.py +461 -0
  435. crackerjack/services/version_checker.py +223 -0
  436. crackerjack/services/websocket_resource_limiter.py +438 -0
  437. crackerjack/services/zuban_lsp_service.py +391 -0
  438. crackerjack/slash_commands/README.md +11 -0
  439. crackerjack/slash_commands/__init__.py +59 -0
  440. crackerjack/slash_commands/init.md +112 -0
  441. crackerjack/slash_commands/run.md +197 -0
  442. crackerjack/slash_commands/status.md +127 -0
  443. crackerjack/tools/README.md +11 -0
  444. crackerjack/tools/__init__.py +30 -0
  445. crackerjack/tools/_git_utils.py +105 -0
  446. crackerjack/tools/check_added_large_files.py +139 -0
  447. crackerjack/tools/check_ast.py +105 -0
  448. crackerjack/tools/check_json.py +103 -0
  449. crackerjack/tools/check_jsonschema.py +297 -0
  450. crackerjack/tools/check_toml.py +103 -0
  451. crackerjack/tools/check_yaml.py +110 -0
  452. crackerjack/tools/codespell_wrapper.py +72 -0
  453. crackerjack/tools/end_of_file_fixer.py +202 -0
  454. crackerjack/tools/format_json.py +128 -0
  455. crackerjack/tools/mdformat_wrapper.py +114 -0
  456. crackerjack/tools/trailing_whitespace.py +198 -0
  457. crackerjack/tools/validate_input_validator_patterns.py +236 -0
  458. crackerjack/tools/validate_regex_patterns.py +188 -0
  459. crackerjack/ui/README.md +11 -0
  460. crackerjack/ui/__init__.py +1 -0
  461. crackerjack/ui/dashboard_renderer.py +28 -0
  462. crackerjack/ui/templates/README.md +11 -0
  463. crackerjack/utils/console_utils.py +13 -0
  464. crackerjack/utils/dependency_guard.py +230 -0
  465. crackerjack/utils/retry_utils.py +275 -0
  466. crackerjack/workflows/README.md +590 -0
  467. crackerjack/workflows/__init__.py +46 -0
  468. crackerjack/workflows/actions.py +811 -0
  469. crackerjack/workflows/auto_fix.py +444 -0
  470. crackerjack/workflows/container_builder.py +499 -0
  471. crackerjack/workflows/definitions.py +443 -0
  472. crackerjack/workflows/engine.py +177 -0
  473. crackerjack/workflows/event_bridge.py +242 -0
  474. crackerjack-0.45.2.dist-info/METADATA +1678 -0
  475. crackerjack-0.45.2.dist-info/RECORD +478 -0
  476. {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
  477. crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
  478. crackerjack/.gitignore +0 -14
  479. crackerjack/.libcst.codemod.yaml +0 -18
  480. crackerjack/.pdm.toml +0 -1
  481. crackerjack/.pre-commit-config.yaml +0 -91
  482. crackerjack/.pytest_cache/.gitignore +0 -2
  483. crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
  484. crackerjack/.pytest_cache/README.md +0 -8
  485. crackerjack/.pytest_cache/v/cache/nodeids +0 -1
  486. crackerjack/.pytest_cache/v/cache/stepwise +0 -1
  487. crackerjack/.ruff_cache/.gitignore +0 -1
  488. crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
  489. crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
  490. crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
  491. crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
  492. crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
  493. crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
  494. crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  495. crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
  496. crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
  497. crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
  498. crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
  499. crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
  500. crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
  501. crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
  502. crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
  503. crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
  504. crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
  505. crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
  506. crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
  507. crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
  508. crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
  509. crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
  510. crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
  511. crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
  512. crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
  513. crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
  514. crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
  515. crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
  516. crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
  517. crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
  518. crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
  519. crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
  520. crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
  521. crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
  522. crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
  523. crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
  524. crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
  525. crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
  526. crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
  527. crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
  528. crackerjack/crackerjack.py +0 -855
  529. crackerjack/pyproject.toml +0 -214
  530. crackerjack-0.18.2.dist-info/METADATA +0 -420
  531. crackerjack-0.18.2.dist-info/RECORD +0 -59
  532. crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
  533. {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,823 @@
1
+ import json
2
+ import subprocess
3
+ import typing as t
4
+ from pathlib import Path
5
+
6
+ import tomli
7
+ import yaml
8
+ from acb.console import Console
9
+ from acb.depends import Inject, depends
10
+
11
+ from crackerjack.models.protocols import ConfigMergeServiceProtocol
12
+
13
+ from .config_merge import ConfigMergeService
14
+ from .filesystem import FileSystemService
15
+ from .git import GitService
16
+ from .input_validator import get_input_validator, validate_and_sanitize_path
17
+
18
+
19
+ class InitializationService:
20
+ @depends.inject
21
+ def __init__(
22
+ self,
23
+ console: Inject[Console],
24
+ filesystem: FileSystemService,
25
+ git_service: GitService,
26
+ pkg_path: Path,
27
+ config_merge_service: ConfigMergeServiceProtocol | None = None,
28
+ ) -> None:
29
+ self.console = console
30
+ self.filesystem = filesystem
31
+ self.git_service = git_service
32
+ self.pkg_path = pkg_path
33
+
34
+ self.config_merge_service = config_merge_service or ConfigMergeService(
35
+ filesystem, git_service
36
+ )
37
+
38
+ def initialize_project(self, project_path: str | Path) -> bool:
39
+ try:
40
+ result = self.initialize_project_full(Path(project_path))
41
+ success = result.get("success", False)
42
+ return bool(success)
43
+ except Exception:
44
+ return False
45
+
46
+ def setup_git_hooks(self) -> bool:
47
+ try:
48
+ return True
49
+ except Exception:
50
+ return False
51
+
52
+ def validate_project_structure(self) -> bool:
53
+ try:
54
+ return True
55
+ except Exception:
56
+ return False
57
+
58
+ def initialize_project_full(
59
+ self,
60
+ target_path: Path | None = None,
61
+ force: bool = False,
62
+ ) -> dict[str, t.Any]:
63
+ if target_path is None:
64
+ target_path = Path.cwd()
65
+
66
+ try:
67
+ target_path = validate_and_sanitize_path(target_path, allow_absolute=True)
68
+ except Exception as e:
69
+ return {
70
+ "target_path": str(target_path),
71
+ "files_copied": [],
72
+ "files_skipped": [],
73
+ "errors": [f"Invalid target path: {e}"],
74
+ "success": False,
75
+ }
76
+
77
+ results = self._create_results_dict(target_path)
78
+
79
+ try:
80
+ config_files = self._get_config_files()
81
+ project_name = target_path.name
82
+
83
+ validator = get_input_validator()
84
+ name_result = validator.validate_project_name(project_name)
85
+ if not name_result.valid:
86
+ results["errors"].append(
87
+ f"Invalid project name: {name_result.error_message}"
88
+ )
89
+ results["success"] = False
90
+ return results
91
+
92
+ sanitized_project_name = name_result.sanitized_value
93
+
94
+ for file_name, merge_strategy in config_files.items():
95
+ self._process_config_file(
96
+ file_name,
97
+ merge_strategy,
98
+ sanitized_project_name,
99
+ target_path,
100
+ force,
101
+ results,
102
+ )
103
+
104
+ self._print_summary(results)
105
+
106
+ except Exception as e:
107
+ self._handle_initialization_error(results, e)
108
+
109
+ return results
110
+
111
+ def _create_results_dict(self, target_path: Path) -> dict[str, t.Any]:
112
+ return {
113
+ "target_path": str(target_path),
114
+ "files_copied": [],
115
+ "files_skipped": [],
116
+ "errors": [],
117
+ "success": True,
118
+ }
119
+
120
+ def _get_config_files(self) -> dict[str, str]:
121
+ # Skip pre-commit configuration to prevent hook installation
122
+ return {
123
+ "pyproject.toml": "smart_merge",
124
+ ".gitignore": "smart_merge_gitignore",
125
+ "CLAUDE.md": "smart_append",
126
+ "RULES.md": "replace_if_missing",
127
+ "example.mcp.json": "special",
128
+ }
129
+
130
+ def _apply_merge_strategy(
131
+ self,
132
+ merge_strategy: str,
133
+ source_file: Path,
134
+ target_file: Path,
135
+ file_name: str,
136
+ project_name: str,
137
+ force: bool,
138
+ results: dict[str, t.Any],
139
+ ) -> None:
140
+ """Apply the appropriate merge strategy for the config file."""
141
+ if merge_strategy == "smart_merge":
142
+ self._smart_merge_config(
143
+ source_file,
144
+ target_file,
145
+ file_name,
146
+ project_name,
147
+ force,
148
+ results,
149
+ )
150
+ elif merge_strategy == "smart_merge_gitignore":
151
+ self._smart_merge_gitignore(
152
+ target_file,
153
+ project_name,
154
+ force,
155
+ results,
156
+ )
157
+ elif merge_strategy == "smart_append":
158
+ self._smart_append_config(
159
+ source_file,
160
+ target_file,
161
+ file_name,
162
+ project_name,
163
+ force,
164
+ results,
165
+ )
166
+ elif merge_strategy == "replace_if_missing":
167
+ self._handle_replace_if_missing(
168
+ source_file,
169
+ target_file,
170
+ file_name,
171
+ project_name,
172
+ force,
173
+ results,
174
+ )
175
+ else:
176
+ self._handle_default_strategy(
177
+ source_file,
178
+ target_file,
179
+ file_name,
180
+ project_name,
181
+ force,
182
+ results,
183
+ )
184
+
185
+ def _handle_replace_if_missing(
186
+ self,
187
+ source_file: Path,
188
+ target_file: Path,
189
+ file_name: str,
190
+ project_name: str,
191
+ force: bool,
192
+ results: dict[str, t.Any],
193
+ ) -> None:
194
+ """Handle replace_if_missing strategy."""
195
+ if not target_file.exists() or force:
196
+ content = self._read_and_process_content(source_file, True, project_name)
197
+ self._write_file_and_track(target_file, content, file_name, results)
198
+ else:
199
+ self._skip_existing_file(file_name, results)
200
+
201
+ def _handle_default_strategy(
202
+ self,
203
+ source_file: Path,
204
+ target_file: Path,
205
+ file_name: str,
206
+ project_name: str,
207
+ force: bool,
208
+ results: dict[str, t.Any],
209
+ ) -> None:
210
+ """Handle default copy strategy."""
211
+ if not self._should_copy_file(target_file, force, file_name, results):
212
+ return
213
+ content = self._read_and_process_content(source_file, True, project_name)
214
+ self._write_file_and_track(target_file, content, file_name, results)
215
+
216
+ def _process_config_file(
217
+ self,
218
+ file_name: str,
219
+ merge_strategy: str,
220
+ project_name: str,
221
+ target_path: Path,
222
+ force: bool,
223
+ results: dict[str, t.Any],
224
+ ) -> None:
225
+ if file_name == "example.mcp.json":
226
+ self._process_mcp_config(target_path, force, results)
227
+ return
228
+
229
+ # Use crackerjack's project root for template files
230
+ crackerjack_project_root = Path(__file__).parent.parent.parent
231
+ source_file = crackerjack_project_root / file_name
232
+ target_file = target_path / file_name
233
+
234
+ if not source_file.exists():
235
+ self._handle_missing_source_file(file_name, results)
236
+ return
237
+
238
+ try:
239
+ self._apply_merge_strategy(
240
+ merge_strategy,
241
+ source_file,
242
+ target_file,
243
+ file_name,
244
+ project_name,
245
+ force,
246
+ results,
247
+ )
248
+ except Exception as e:
249
+ self._handle_file_processing_error(file_name, e, results)
250
+
251
+ def _should_copy_file(
252
+ self,
253
+ target_file: Path,
254
+ force: bool,
255
+ file_name: str,
256
+ results: dict[str, t.Any],
257
+ ) -> bool:
258
+ if target_file.exists() and not force:
259
+ t.cast("list[str]", results["files_skipped"]).append(file_name)
260
+ self.console.print(
261
+ f"[yellow]⚠️[/ yellow] Skipped {file_name} (already exists)",
262
+ )
263
+ return False
264
+ return True
265
+
266
+ def _read_and_process_content(
267
+ self,
268
+ source_file: Path,
269
+ should_replace: bool,
270
+ project_name: str,
271
+ ) -> str:
272
+ content = source_file.read_text()
273
+
274
+ if should_replace and project_name != "crackerjack":
275
+ content = content.replace("crackerjack", project_name)
276
+
277
+ return content
278
+
279
+ def _write_file_and_track(
280
+ self,
281
+ target_file: Path,
282
+ content: str,
283
+ file_name: str,
284
+ results: dict[str, t.Any],
285
+ ) -> None:
286
+ target_file.write_text(content)
287
+ t.cast("list[str]", results["files_copied"]).append(file_name)
288
+
289
+ try:
290
+ self.git_service.add_files([str(target_file)])
291
+ except Exception as e:
292
+ self.console.print(
293
+ f"[yellow]⚠️[/ yellow] Could not git add {file_name}: {e}"
294
+ )
295
+
296
+ self.console.print(f"[green]✅[/ green] Copied {file_name}")
297
+
298
+ def _skip_existing_file(self, file_name: str, results: dict[str, t.Any]) -> None:
299
+ t.cast("list[str]", results["files_skipped"]).append(file_name)
300
+ self.console.print(f"[yellow]⚠️[/ yellow] Skipped {file_name} (already exists)")
301
+
302
+ def _handle_missing_source_file(
303
+ self,
304
+ file_name: str,
305
+ results: dict[str, t.Any],
306
+ ) -> None:
307
+ error_msg = f"Source file not found: {file_name}"
308
+ t.cast("list[str]", results["errors"]).append(error_msg)
309
+ self.console.print(f"[yellow]⚠️[/ yellow] {error_msg}")
310
+
311
+ def _handle_file_processing_error(
312
+ self,
313
+ file_name: str,
314
+ error: Exception,
315
+ results: dict[str, t.Any],
316
+ ) -> None:
317
+ error_msg = f"Failed to copy {file_name}: {error}"
318
+ t.cast("list[str]", results["errors"]).append(error_msg)
319
+ results["success"] = False
320
+ self.console.print(f"[red]❌[/ red] {error_msg}")
321
+
322
+ def _print_summary(self, results: dict[str, t.Any]) -> None:
323
+ if results["success"]:
324
+ self.console.print(
325
+ f"[green]🎉 Project initialized successfully ! [/ green] "
326
+ f"Copied {len(t.cast('list[str]', results['files_copied']))} files",
327
+ )
328
+ else:
329
+ self.console.print(
330
+ "[red]❌ Project initialization completed with errors[/ red]",
331
+ )
332
+
333
+ def _handle_initialization_error(
334
+ self,
335
+ results: dict[str, t.Any],
336
+ error: Exception,
337
+ ) -> None:
338
+ results["success"] = False
339
+ t.cast("list[str]", results["errors"]).append(f"Initialization failed: {error}")
340
+ self.console.print(f"[red]❌[/ red] Initialization failed: {error}")
341
+
342
+ def check_uv_installed(self) -> bool:
343
+ try:
344
+ result = subprocess.run(
345
+ ["uv", "--version"],
346
+ capture_output=True,
347
+ text=True,
348
+ timeout=10,
349
+ check=False,
350
+ )
351
+ return result.returncode == 0
352
+ except (FileNotFoundError, subprocess.TimeoutExpired):
353
+ return False
354
+
355
+ def _process_mcp_config(
356
+ self,
357
+ target_path: Path,
358
+ force: bool,
359
+ results: dict[str, t.Any],
360
+ ) -> None:
361
+ # Use crackerjack's project root for template files
362
+ crackerjack_project_root = Path(__file__).parent.parent.parent
363
+ source_file = crackerjack_project_root / "example.mcp.json"
364
+
365
+ target_file = target_path / ".mcp.json"
366
+
367
+ if not source_file.exists():
368
+ self._handle_missing_source_file("example.mcp.json", results)
369
+ return
370
+
371
+ try:
372
+ with source_file.open() as f:
373
+ source_config = json.load(f)
374
+
375
+ if not isinstance(source_config.get("mcpServers"), dict):
376
+ self._handle_file_processing_error(
377
+ "example.mcp.json",
378
+ ValueError("Invalid example.mcp.json format: missing mcpServers"),
379
+ results,
380
+ )
381
+ return
382
+
383
+ crackerjack_servers = source_config["mcpServers"]
384
+
385
+ if not target_file.exists():
386
+ target_config = {"mcpServers": crackerjack_servers}
387
+ self._write_mcp_config_and_track(target_file, target_config, results)
388
+ self.console.print(
389
+ "[green]✅[/ green] Created .mcp.json with crackerjack MCP servers",
390
+ )
391
+ return
392
+
393
+ if target_file.exists() and not force:
394
+ self._merge_mcp_config(target_file, crackerjack_servers, results)
395
+ return
396
+
397
+ target_config = {"mcpServers": crackerjack_servers}
398
+ self._write_mcp_config_and_track(target_file, target_config, results)
399
+ self.console.print(
400
+ "[green]✅[/ green] Updated .mcp.json with crackerjack MCP servers",
401
+ )
402
+
403
+ except Exception as e:
404
+ self._handle_file_processing_error(".mcp.json", e, results)
405
+
406
+ def _merge_mcp_config(
407
+ self,
408
+ target_file: Path,
409
+ crackerjack_servers: dict[str, t.Any],
410
+ results: dict[str, t.Any],
411
+ ) -> None:
412
+ try:
413
+ with target_file.open() as f:
414
+ existing_config = json.load(f)
415
+
416
+ if not isinstance(existing_config.get("mcpServers"), dict):
417
+ existing_config["mcpServers"] = {}
418
+
419
+ existing_servers = existing_config["mcpServers"]
420
+ updated_servers = {}
421
+
422
+ for name, config in crackerjack_servers.items():
423
+ if name in existing_servers:
424
+ self.console.print(
425
+ f"[yellow]🔄[/ yellow] Updating existing MCP server: {name}",
426
+ )
427
+ else:
428
+ self.console.print(
429
+ f"[green]➕[/ green] Adding new MCP server: {name}",
430
+ )
431
+ updated_servers[name] = config
432
+
433
+ existing_servers.update(updated_servers)
434
+
435
+ self._write_mcp_config_and_track(target_file, existing_config, results)
436
+
437
+ t.cast("list[str]", results["files_copied"]).append(".mcp.json (merged)")
438
+
439
+ except Exception as e:
440
+ self._handle_file_processing_error(".mcp.json (merge)", e, results)
441
+
442
+ def _write_mcp_config_and_track(
443
+ self,
444
+ target_file: Path,
445
+ config: dict[str, t.Any],
446
+ results: dict[str, t.Any],
447
+ ) -> None:
448
+ with target_file.open("w") as f:
449
+ json.dump(config, f, indent=2)
450
+
451
+ t.cast("list[str]", results["files_copied"]).append(".mcp.json")
452
+
453
+ try:
454
+ self.git_service.add_files([str(target_file)])
455
+ except Exception as e:
456
+ self.console.print(f"[yellow]⚠️[/ yellow] Could not git add .mcp.json: {e}")
457
+
458
+ def _generate_project_claude_content(self, project_name: str) -> str:
459
+ return """
460
+
461
+
462
+ This project uses crackerjack for Python project management and quality assurance.
463
+
464
+
465
+ For optimal development experience with this crackerjack - enabled project, use these specialized agents:
466
+
467
+
468
+ - **🏗️ crackerjack-architect**: Expert in crackerjack's modular architecture and Python project management patterns. **Use PROACTIVELY** for all feature development, architectural decisions, and ensuring code follows crackerjack standards from the start.
469
+
470
+ - **🐍 python-pro**: Modern Python development with type hints, async/await patterns, and clean architecture
471
+
472
+ - **🧪 pytest-hypothesis-specialist**: Advanced testing patterns, property-based testing, and test optimization
473
+
474
+
475
+ - **🧪 crackerjack-test-specialist**: Advanced testing specialist for complex testing scenarios and coverage optimization
476
+ - **🏗️ backend-architect**: System design, API architecture, and service integration patterns
477
+ - **🔒 security-auditor**: Security analysis, vulnerability detection, and secure coding practices
478
+
479
+
480
+ ```bash
481
+
482
+ Task tool with subagent_type ="crackerjack-architect" for feature planning
483
+
484
+
485
+ Task tool with subagent_type ="python-pro" for code implementation
486
+
487
+
488
+ Task tool with subagent_type ="pytest-hypothesis-specialist" for test development
489
+
490
+
491
+ Task tool with subagent_type ="security-auditor" for security analysis
492
+ ```
493
+
494
+ **💡 Pro Tip**: The crackerjack-architect agent automatically ensures code follows crackerjack patterns from the start, eliminating the need for retrofitting and quality fixes.
495
+
496
+
497
+ This project follows crackerjack's clean code philosophy:
498
+
499
+
500
+ - **EVERY LINE OF CODE IS A LIABILITY**: The best code is no code
501
+ - **DRY (Don't Repeat Yourself)**: If you write it twice, you're doing it wrong
502
+ - **YAGNI (You Ain't Gonna Need It)**: Build only what's needed NOW
503
+ - **KISS (Keep It Simple, Stupid)**: Complexity is the enemy of maintainability
504
+
505
+
506
+ - **Cognitive complexity ≤15 **per function (automatically enforced)
507
+ - **Coverage ratchet system**: Never decrease coverage, always improve toward 100%
508
+ - **Type annotations required**: All functions must have return type hints
509
+ - **Security patterns**: No hardcoded paths, proper temp file handling
510
+ - **Python 3.13+ modern patterns**: Use `|` unions, pathlib over os.path
511
+
512
+
513
+ ```bash
514
+
515
+ python -m crackerjack
516
+
517
+
518
+ python -m crackerjack - t
519
+
520
+
521
+ python -m crackerjack - - ai - agent - t
522
+
523
+
524
+ python -m crackerjack - a patch
525
+ ```
526
+
527
+
528
+ 1. **Plan with crackerjack-architect**: Ensure proper architecture from the start
529
+ 2. **Implement with python-pro**: Follow modern Python patterns
530
+ 3. **Test comprehensively**: Use pytest-hypothesis-specialist for robust testing
531
+ 4. **Run quality checks**: `python -m crackerjack -t` before committing
532
+ 5. **Security review**: Use security-auditor for final validation
533
+
534
+
535
+ - **Use crackerjack-architect agent proactively** for all significant code changes
536
+ - **Never reduce test coverage** - the ratchet system only allows improvements
537
+ - **Follow crackerjack patterns** - the tools will enforce quality automatically
538
+ - **Leverage AI agent auto-fixing** - `python -m crackerjack --ai-agent -t` for autonomous quality fixes
539
+
540
+ - --
541
+ * This project is enhanced by crackerjack's intelligent Python project management.*"""
542
+
543
+ def _smart_append_config(
544
+ self,
545
+ source_file: Path,
546
+ target_file: Path,
547
+ file_name: str,
548
+ project_name: str,
549
+ force: bool,
550
+ results: dict[str, t.Any],
551
+ ) -> None:
552
+ try:
553
+ if file_name == "CLAUDE.md" and project_name != "crackerjack":
554
+ source_content = self._generate_project_claude_content(project_name)
555
+ else:
556
+ source_content = self._read_and_process_content(
557
+ source_file, True, project_name
558
+ )
559
+
560
+ crackerjack_start_marker = "<!-- CRACKERJACK INTEGRATION START -->"
561
+ crackerjack_end_marker = "<!-- CRACKERJACK INTEGRATION END -->"
562
+
563
+ merged_content = self.config_merge_service.smart_append_file(
564
+ source_content,
565
+ target_file,
566
+ crackerjack_start_marker,
567
+ crackerjack_end_marker,
568
+ force,
569
+ )
570
+
571
+ if target_file.exists():
572
+ existing_content = target_file.read_text()
573
+ if crackerjack_start_marker in existing_content and not force:
574
+ self._skip_existing_file(
575
+ f"{file_name} (crackerjack section)", results
576
+ )
577
+ return
578
+
579
+ target_file.write_text(merged_content)
580
+ t.cast("list[str]", results["files_copied"]).append(
581
+ f"{file_name} (appended)"
582
+ )
583
+
584
+ try:
585
+ self.git_service.add_files([str(target_file)])
586
+ except Exception as e:
587
+ self.console.print(
588
+ f"[yellow]⚠️[/ yellow] Could not git add {file_name}: {e}"
589
+ )
590
+
591
+ self.console.print(f"[green]✅[/ green] Appended to {file_name}")
592
+
593
+ except Exception as e:
594
+ self._handle_file_processing_error(file_name, e, results)
595
+
596
+ def _smart_merge_gitignore(
597
+ self,
598
+ target_file: Path,
599
+ project_name: str,
600
+ force: bool,
601
+ results: dict[str, t.Any],
602
+ ) -> None:
603
+ gitignore_patterns = [
604
+ "# Build/Distribution",
605
+ "/build/",
606
+ "/dist/",
607
+ "*.egg-info/",
608
+ "",
609
+ "# Caches",
610
+ "__pycache__/",
611
+ ".mypy_cache/",
612
+ ".ruff_cache/",
613
+ ".pytest_cache/",
614
+ "",
615
+ "# Coverage",
616
+ ".coverage*",
617
+ "htmlcov/",
618
+ "",
619
+ "# Development",
620
+ ".venv/",
621
+ ".DS_STORE",
622
+ "*.pyc",
623
+ "",
624
+ "# Crackerjack specific",
625
+ "crackerjack-debug-*.log",
626
+ "crackerjack-ai-debug-*.log",
627
+ ".crackerjack-*",
628
+ ]
629
+
630
+ try:
631
+ merged_content = self.config_merge_service.smart_merge_gitignore(
632
+ gitignore_patterns, target_file
633
+ )
634
+
635
+ target_file.write_text(merged_content)
636
+ t.cast("list[str]", results["files_copied"]).append(".gitignore (merged)")
637
+
638
+ try:
639
+ self.git_service.add_files([str(target_file)])
640
+ except Exception as e:
641
+ self.console.print(
642
+ f"[yellow]⚠️[/ yellow] Could not git add .gitignore: {e}"
643
+ )
644
+
645
+ self.console.print("[green]✅[/ green] Smart merged .gitignore")
646
+
647
+ except Exception as e:
648
+ self._handle_file_processing_error(".gitignore", e, results)
649
+
650
+ def _smart_merge_config(
651
+ self,
652
+ source_file: Path,
653
+ target_file: Path,
654
+ file_name: str,
655
+ project_name: str,
656
+ force: bool,
657
+ results: dict[str, t.Any],
658
+ ) -> None:
659
+ if file_name == "pyproject.toml":
660
+ self._smart_merge_pyproject(
661
+ source_file,
662
+ target_file,
663
+ project_name,
664
+ force,
665
+ results,
666
+ )
667
+ elif file_name == ".pre-commit-config.yaml":
668
+ self._smart_merge_pre_commit_config(
669
+ source_file,
670
+ target_file,
671
+ project_name,
672
+ force,
673
+ results,
674
+ )
675
+ elif not target_file.exists() or force:
676
+ content = self._read_and_process_content(
677
+ source_file,
678
+ True,
679
+ project_name,
680
+ )
681
+ self._write_file_and_track(target_file, content, file_name, results)
682
+ else:
683
+ self._skip_existing_file(file_name, results)
684
+
685
+ def _smart_merge_pyproject(
686
+ self,
687
+ source_file: Path,
688
+ target_file: Path,
689
+ project_name: str,
690
+ force: bool,
691
+ results: dict[str, t.Any],
692
+ ) -> None:
693
+ try:
694
+ with source_file.open("rb") as f:
695
+ source_config = tomli.load(f)
696
+
697
+ merged_config = self.config_merge_service.smart_merge_pyproject(
698
+ source_config, target_file, project_name
699
+ )
700
+
701
+ self.config_merge_service.write_pyproject_config(merged_config, target_file)
702
+
703
+ t.cast("list[str]", results["files_copied"]).append(
704
+ "pyproject.toml (merged)"
705
+ )
706
+
707
+ try:
708
+ self.git_service.add_files([str(target_file)])
709
+ except Exception as e:
710
+ self.console.print(
711
+ f"[yellow]⚠️[/ yellow] Could not git add pyproject.toml: {e}",
712
+ )
713
+
714
+ self.console.print("[green]✅[/ green] Smart merged pyproject.toml")
715
+
716
+ except Exception as e:
717
+ self._handle_file_processing_error("pyproject.toml", e, results)
718
+
719
+ def _smart_merge_pre_commit_config(
720
+ self,
721
+ source_file: Path,
722
+ target_file: Path,
723
+ project_name: str,
724
+ force: bool,
725
+ results: dict[str, t.Any],
726
+ ) -> None:
727
+ try:
728
+ source_config = self._load_source_config(source_file)
729
+ if source_config is None:
730
+ return
731
+
732
+ merged_config = self._perform_config_merge(
733
+ source_config, target_file, project_name
734
+ )
735
+
736
+ if self._should_skip_merge(target_file, merged_config, results):
737
+ return
738
+
739
+ self._write_and_finalize_config(
740
+ merged_config, target_file, source_config, results
741
+ )
742
+
743
+ except Exception as e:
744
+ self._handle_file_processing_error(".pre-commit-config.yaml", e, results)
745
+
746
+ def _load_source_config(self, source_file: Path) -> dict[str, t.Any] | None:
747
+ with source_file.open() as f:
748
+ loaded_config = yaml.safe_load(f)
749
+ source_config: dict[str, t.Any] = (
750
+ loaded_config if isinstance(loaded_config, dict) else {}
751
+ )
752
+
753
+ if not isinstance(source_config, dict):
754
+ self.console.print(
755
+ "[yellow]⚠️[/yellow] Source .pre-commit-config.yaml is not a dictionary, skipping merge"
756
+ )
757
+ return None
758
+
759
+ return source_config
760
+
761
+ def _perform_config_merge(
762
+ self, source_config: dict[str, t.Any], target_file: Path, project_name: str
763
+ ) -> dict[str, t.Any]:
764
+ return self.config_merge_service.smart_merge_pre_commit_config(
765
+ source_config, target_file, project_name
766
+ )
767
+
768
+ def _should_skip_merge(
769
+ self,
770
+ target_file: Path,
771
+ merged_config: dict[str, t.Any],
772
+ results: dict[str, t.Any],
773
+ ) -> bool:
774
+ if not target_file.exists():
775
+ return False
776
+
777
+ with target_file.open() as f:
778
+ loaded_config = yaml.safe_load(f)
779
+ old_config: dict[str, t.Any] = (
780
+ loaded_config if isinstance(loaded_config, dict) else {}
781
+ )
782
+
783
+ if not isinstance(old_config, dict):
784
+ old_config = {}
785
+
786
+ old_repo_count = len(old_config.get("repos", []))
787
+ new_repo_count = len(merged_config.get("repos", []))
788
+
789
+ if new_repo_count == old_repo_count:
790
+ self._skip_existing_file(".pre-commit-config.yaml (no new repos)", results)
791
+ return True
792
+
793
+ return False
794
+
795
+ def _write_and_finalize_config(
796
+ self,
797
+ merged_config: dict[str, t.Any],
798
+ target_file: Path,
799
+ source_config: dict[str, t.Any],
800
+ results: dict[str, t.Any],
801
+ ) -> None:
802
+ self.config_merge_service.write_pre_commit_config(merged_config, target_file)
803
+
804
+ t.cast("list[str]", results["files_copied"]).append(
805
+ ".pre-commit-config.yaml (merged)"
806
+ )
807
+
808
+ self._git_add_config_file(target_file)
809
+ self._display_merge_success(source_config)
810
+
811
+ def _git_add_config_file(self, target_file: Path) -> None:
812
+ try:
813
+ self.git_service.add_files([str(target_file)])
814
+ except Exception as e:
815
+ self.console.print(
816
+ f"[yellow]⚠️[/ yellow] Could not git add .pre-commit-config.yaml: {e}"
817
+ )
818
+
819
+ def _display_merge_success(self, source_config: dict[str, t.Any]) -> None:
820
+ source_repo_count = len(source_config.get("repos", []))
821
+ self.console.print(
822
+ f"[green]✅[/ green] Merged .pre-commit-config.yaml ({source_repo_count} repos processed)"
823
+ )