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,1065 @@
1
+ """Reference generator for comprehensive command documentation.
2
+
3
+ This module provides automatic generation of command reference documentation
4
+ from CLI definitions, including usage examples, parameter descriptions, and
5
+ workflow integration guides.
6
+ """
7
+
8
+ import ast
9
+ import typing as t
10
+ from dataclasses import dataclass, field
11
+ from datetime import datetime
12
+ from enum import Enum
13
+ from pathlib import Path
14
+
15
+ from ..models.protocols import (
16
+ ConfigManagerProtocol,
17
+ LoggerProtocol,
18
+ )
19
+
20
+
21
+ class ReferenceFormat(Enum):
22
+ """Formats for reference documentation."""
23
+
24
+ MARKDOWN = "markdown"
25
+ HTML = "html"
26
+ JSON = "json"
27
+ YAML = "yaml"
28
+ RST = "rst"
29
+
30
+
31
+ @dataclass
32
+ class ParameterInfo:
33
+ """Information about a command parameter."""
34
+
35
+ name: str
36
+ type_hint: str
37
+ default_value: t.Any
38
+ description: str
39
+ required: bool = False
40
+ choices: list[str] | None = None
41
+ example: str | None = None
42
+ deprecated: bool = False
43
+ added_in_version: str | None = None
44
+
45
+
46
+ @dataclass
47
+ class CommandInfo:
48
+ """Information about a CLI command."""
49
+
50
+ name: str
51
+ description: str
52
+ category: str
53
+ parameters: list[ParameterInfo] = field(default_factory=list)
54
+ examples: list[dict[str, str]] = field(default_factory=list)
55
+ related_commands: list[str] = field(default_factory=list)
56
+ aliases: list[str] = field(default_factory=list)
57
+ deprecated: bool = False
58
+ added_in_version: str | None = None
59
+
60
+ # Workflow integration
61
+ common_workflows: list[str] = field(default_factory=list)
62
+ prerequisites: list[str] = field(default_factory=list)
63
+ side_effects: list[str] = field(default_factory=list)
64
+
65
+ # AI optimization
66
+ ai_context: dict[str, t.Any] = field(default_factory=dict[str, t.Any])
67
+ success_patterns: list[str] = field(default_factory=list)
68
+ failure_patterns: list[str] = field(default_factory=list)
69
+
70
+
71
+ @dataclass
72
+ class CommandReference:
73
+ """Complete command reference documentation."""
74
+
75
+ commands: dict[str, CommandInfo]
76
+ categories: dict[str, list[str]]
77
+ workflows: dict[str, list[str]]
78
+ generated_at: datetime = field(default_factory=datetime.now)
79
+ version: str = "unknown"
80
+
81
+ def get_commands_by_category(self, category: str) -> list[CommandInfo]:
82
+ """Get all commands in a specific category.
83
+
84
+ Args:
85
+ category: Category name
86
+
87
+ Returns:
88
+ List of commands in category
89
+ """
90
+ return [cmd for cmd in self.commands.values() if cmd.category == category]
91
+
92
+ def get_command_by_name(self, name: str) -> CommandInfo | None:
93
+ """Get command by name or alias.
94
+
95
+ Args:
96
+ name: Command name or alias
97
+
98
+ Returns:
99
+ Command info if found, None otherwise
100
+ """
101
+ # Direct name match
102
+ if name in self.commands:
103
+ return self.commands[name]
104
+
105
+ # Alias match
106
+ for cmd in self.commands.values():
107
+ if name in cmd.aliases:
108
+ return cmd
109
+
110
+ return None
111
+
112
+
113
+ class ReferenceGenerator:
114
+ """Generator for comprehensive command reference documentation."""
115
+
116
+ def __init__(
117
+ self,
118
+ config_manager: ConfigManagerProtocol,
119
+ logger: LoggerProtocol,
120
+ ):
121
+ self.config_manager = config_manager
122
+ self.logger = logger
123
+
124
+ async def generate_reference(
125
+ self,
126
+ cli_module_path: str,
127
+ output_format: ReferenceFormat = ReferenceFormat.MARKDOWN,
128
+ include_examples: bool = True,
129
+ include_workflows: bool = True,
130
+ ) -> CommandReference:
131
+ """Generate command reference from CLI module.
132
+
133
+ Args:
134
+ cli_module_path: Path to CLI module to analyze
135
+ output_format: Output format for documentation
136
+ include_examples: Whether to include usage examples
137
+ include_workflows: Whether to include workflow information
138
+
139
+ Returns:
140
+ Generated command reference
141
+ """
142
+ self.logger.info(f"Generating command reference from: {cli_module_path}")
143
+
144
+ # Analyze CLI module
145
+ commands = await self._analyze_cli_module(cli_module_path)
146
+
147
+ # Enhance with examples if requested
148
+ if include_examples:
149
+ commands = await self._enhance_with_examples(commands)
150
+
151
+ # Enhance with workflows if requested
152
+ if include_workflows:
153
+ commands = await self._enhance_with_workflows(commands)
154
+
155
+ # Categorize commands
156
+ categories = self._categorize_commands(commands)
157
+
158
+ # Generate workflows
159
+ workflows = self._generate_workflows(commands) if include_workflows else {}
160
+
161
+ reference = CommandReference(
162
+ commands=commands,
163
+ categories=categories,
164
+ workflows=workflows,
165
+ )
166
+
167
+ self.logger.info(f"Generated reference for {len(commands)} commands")
168
+ return reference
169
+
170
+ async def render_reference(
171
+ self,
172
+ reference: CommandReference,
173
+ output_format: ReferenceFormat,
174
+ template_name: str | None = None,
175
+ ) -> str:
176
+ """Render command reference to specified format.
177
+
178
+ Args:
179
+ reference: Command reference to render
180
+ output_format: Output format
181
+ template_name: Optional template name to use
182
+
183
+ Returns:
184
+ Rendered reference documentation
185
+ """
186
+ if output_format == ReferenceFormat.MARKDOWN:
187
+ return self._render_markdown(reference)
188
+ elif output_format == ReferenceFormat.HTML:
189
+ return self._render_html(reference)
190
+ elif output_format == ReferenceFormat.JSON:
191
+ return self._render_json(reference)
192
+ elif output_format == ReferenceFormat.YAML:
193
+ return self._render_yaml(reference)
194
+ elif output_format == ReferenceFormat.RST:
195
+ return self._render_rst(reference)
196
+ else:
197
+ raise ValueError(f"Unsupported format: {output_format}")
198
+
199
+ async def _analyze_cli_module(self, module_path: str) -> dict[str, CommandInfo]:
200
+ """Analyze CLI module to extract command information.
201
+
202
+ Args:
203
+ module_path: Path to CLI module
204
+
205
+ Returns:
206
+ Dictionary of command name to CommandInfo
207
+ """
208
+ commands = {}
209
+
210
+ try:
211
+ # Read and parse the module
212
+ module_file = Path(module_path)
213
+ if not module_file.exists():
214
+ raise FileNotFoundError(f"CLI module not found: {module_path}")
215
+
216
+ source_code = module_file.read_text()
217
+
218
+ # Parse AST
219
+ tree = ast.parse(source_code)
220
+
221
+ # Extract command information
222
+ commands = self._extract_commands_from_ast(tree)
223
+
224
+ except Exception as e:
225
+ self.logger.error(f"Failed to analyze CLI module: {e}")
226
+
227
+ return commands
228
+
229
+ def _extract_commands_from_ast(self, tree: ast.AST) -> dict[str, CommandInfo]:
230
+ """Extract command information from AST.
231
+
232
+ Args:
233
+ tree: Parsed AST
234
+
235
+ Returns:
236
+ Dictionary of commands
237
+ """
238
+ commands: dict[str, CommandInfo] = {}
239
+ visitor = self._create_command_visitor(commands)
240
+ visitor.visit(tree)
241
+ return commands
242
+
243
+ def _create_command_visitor(
244
+ self, commands: dict[str, CommandInfo]
245
+ ) -> ast.NodeVisitor:
246
+ """Create AST visitor for command extraction.
247
+
248
+ Args:
249
+ commands: Dictionary to populate with commands
250
+
251
+ Returns:
252
+ Configured AST visitor
253
+ """
254
+
255
+ class CommandVisitor(ast.NodeVisitor):
256
+ def __init__(self, generator: t.Any) -> None:
257
+ self.generator = generator
258
+
259
+ def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
260
+ self.generator._process_function_node(node, commands)
261
+ self.generic_visit(node)
262
+
263
+ return CommandVisitor(self)
264
+
265
+ def _process_function_node(
266
+ self, node: ast.FunctionDef, commands: dict[str, CommandInfo]
267
+ ) -> None:
268
+ """Process function node for command extraction.
269
+
270
+ Args:
271
+ node: Function definition node
272
+ commands: Commands dictionary to update
273
+ """
274
+ for decorator in node.decorator_list:
275
+ if self._is_command_decorator(decorator):
276
+ command_info = self._extract_command_from_function(node)
277
+ if command_info:
278
+ commands[command_info.name] = command_info
279
+
280
+ def _is_command_decorator(self, decorator: ast.AST) -> bool:
281
+ """Check if decorator indicates a CLI command.
282
+
283
+ Args:
284
+ decorator: AST decorator node
285
+
286
+ Returns:
287
+ True if command decorator
288
+ """
289
+ if isinstance(decorator, ast.Name):
290
+ return decorator.id in ("command", "click_command")
291
+ elif isinstance(decorator, ast.Attribute):
292
+ return decorator.attr in ("command", "callback")
293
+ return False
294
+
295
+ def _extract_command_from_function(
296
+ self, node: ast.FunctionDef
297
+ ) -> CommandInfo | None:
298
+ """Extract command info from function definition.
299
+
300
+ Args:
301
+ node: Function definition node
302
+
303
+ Returns:
304
+ Command info or None if extraction fails
305
+ """
306
+ try:
307
+ command_name = node.name.replace("_", "-")
308
+ description = self._extract_docstring(node)
309
+ parameters = self._extract_function_parameters(node)
310
+
311
+ return CommandInfo(
312
+ name=command_name,
313
+ description=description or f"Execute {command_name}",
314
+ category="general",
315
+ parameters=parameters,
316
+ )
317
+
318
+ except Exception as e:
319
+ self.logger.warning(f"Failed to extract command {node.name}: {e}")
320
+ return None
321
+
322
+ def _extract_function_parameters(
323
+ self, node: ast.FunctionDef
324
+ ) -> list[ParameterInfo]:
325
+ """Extract parameter information from function.
326
+
327
+ Args:
328
+ node: Function definition node
329
+
330
+ Returns:
331
+ List of parameter information
332
+ """
333
+ parameters = []
334
+ for arg in node.args.args:
335
+ if arg.arg != "self":
336
+ param_info = self._extract_parameter_info(arg, node)
337
+ parameters.append(param_info)
338
+ return parameters
339
+
340
+ def _extract_docstring(self, node: ast.FunctionDef) -> str | None:
341
+ """Extract docstring from function.
342
+
343
+ Args:
344
+ node: Function definition node
345
+
346
+ Returns:
347
+ Docstring or None
348
+ """
349
+ if (
350
+ node.body
351
+ and isinstance(node.body[0], ast.Expr)
352
+ and isinstance(node.body[0].value, ast.Constant)
353
+ and isinstance(node.body[0].value.value, str)
354
+ ):
355
+ return node.body[0].value.value.strip()
356
+ return None
357
+
358
+ def _extract_parameter_info(
359
+ self, arg: ast.arg, func_node: ast.FunctionDef
360
+ ) -> ParameterInfo:
361
+ """Extract parameter information.
362
+
363
+ Args:
364
+ arg: Function argument node
365
+ func_node: Parent function node
366
+
367
+ Returns:
368
+ Parameter information
369
+ """
370
+ param_name = arg.arg.replace("_", "-")
371
+ type_hint = ast.unparse(arg.annotation) if arg.annotation else "Any"
372
+ default_value, required = self._extract_default_value(arg, func_node)
373
+
374
+ return ParameterInfo(
375
+ name=param_name,
376
+ type_hint=type_hint,
377
+ default_value=default_value,
378
+ description=f"Parameter: {param_name}",
379
+ required=required,
380
+ )
381
+
382
+ def _extract_default_value(
383
+ self, arg: ast.arg, func_node: ast.FunctionDef
384
+ ) -> tuple[t.Any, bool]:
385
+ """Extract default value and required status for parameter.
386
+
387
+ Args:
388
+ arg: Function argument node
389
+ func_node: Parent function node
390
+
391
+ Returns:
392
+ Tuple of (default_value, required)
393
+ """
394
+ defaults_count = len(func_node.args.defaults)
395
+ args_count = len(func_node.args.args)
396
+ defaults_start = args_count - defaults_count
397
+
398
+ arg_index = func_node.args.args.index(arg)
399
+ if arg_index >= defaults_start:
400
+ return self._extract_argument_default(arg_index, defaults_start, func_node)
401
+
402
+ return None, True
403
+
404
+ def _extract_argument_default(
405
+ self, arg_index: int, defaults_start: int, func_node: ast.FunctionDef
406
+ ) -> tuple[t.Any, bool]:
407
+ """Extract default value for a specific argument.
408
+
409
+ Args:
410
+ arg_index: Index of the argument
411
+ defaults_start: Index where defaults start
412
+ func_node: Parent function node
413
+
414
+ Returns:
415
+ Tuple of (default_value, required)
416
+ """
417
+ default_index = arg_index - defaults_start
418
+ default_node = func_node.args.defaults[default_index]
419
+ if isinstance(default_node, ast.Constant):
420
+ return default_node.value, False
421
+ return None, True
422
+
423
+ async def _enhance_with_examples(
424
+ self, commands: dict[str, CommandInfo]
425
+ ) -> dict[str, CommandInfo]:
426
+ """Enhance commands with usage examples.
427
+
428
+ Args:
429
+ commands: Commands to enhance
430
+
431
+ Returns:
432
+ Enhanced commands with examples
433
+ """
434
+ for command in commands.values():
435
+ self._add_basic_example(command)
436
+ self._add_parameter_examples(command)
437
+ return commands
438
+
439
+ def _add_basic_example(self, command: CommandInfo) -> None:
440
+ """Add a basic example for a command."""
441
+ basic_example = f"python -m crackerjack --{command.name}"
442
+ command.examples.append(
443
+ {
444
+ "description": f"Basic {command.name} usage",
445
+ "command": basic_example,
446
+ }
447
+ )
448
+
449
+ def _add_parameter_examples(self, command: CommandInfo) -> None:
450
+ """Add parameter examples for a command."""
451
+ # Generate basic examples
452
+ basic_example = f"python -m crackerjack --{command.name}"
453
+
454
+ # Add parameter examples
455
+ param_examples = []
456
+ for param in command.parameters:
457
+ if not param.required and param.default_value is not None:
458
+ param_example = self._format_parameter_example(param)
459
+ if param_example:
460
+ param_examples.append(param_example)
461
+
462
+ if param_examples:
463
+ enhanced_example = f"{basic_example} {' '.join(param_examples)}"
464
+ command.examples.append(
465
+ {
466
+ "description": f"Using {command.name} with parameters",
467
+ "command": enhanced_example,
468
+ }
469
+ )
470
+
471
+ def _format_parameter_example(self, param: ParameterInfo) -> str | None:
472
+ """Format a parameter example."""
473
+ if isinstance(param.default_value, bool):
474
+ return f"--{param.name}"
475
+ return f"--{param.name} {param.default_value}"
476
+
477
+ async def _enhance_with_workflows(
478
+ self, commands: dict[str, CommandInfo]
479
+ ) -> dict[str, CommandInfo]:
480
+ """Enhance commands with workflow information.
481
+
482
+ Args:
483
+ commands: Commands to enhance
484
+
485
+ Returns:
486
+ Enhanced commands with workflow info
487
+ """
488
+ workflow_patterns = self._get_workflow_patterns()
489
+
490
+ for command in commands.values():
491
+ self._assign_command_workflows(command, workflow_patterns)
492
+ self._add_ai_context_to_command(command)
493
+
494
+ return commands
495
+
496
+ def _get_workflow_patterns(self) -> dict[str, list[str]]:
497
+ """Get workflow patterns for command categorization.
498
+
499
+ Returns:
500
+ Dictionary mapping workflow names to pattern lists
501
+ """
502
+ return {
503
+ "development": ["test", "format", "lint", "type-check"],
504
+ "release": ["version", "build", "publish", "tag"],
505
+ "maintenance": ["clean", "update", "optimize", "backup"],
506
+ "monitoring": ["status", "health", "metrics", "logs"],
507
+ }
508
+
509
+ def _assign_command_workflows(
510
+ self, command: CommandInfo, workflow_patterns: dict[str, list[str]]
511
+ ) -> None:
512
+ """Assign workflows to a command based on name patterns.
513
+
514
+ Args:
515
+ command: Command to assign workflows to
516
+ workflow_patterns: Workflow patterns to match against
517
+ """
518
+ for workflow, patterns in workflow_patterns.items():
519
+ if any(pattern in command.name for pattern in patterns):
520
+ command.common_workflows.append(workflow)
521
+
522
+ def _add_ai_context_to_command(self, command: CommandInfo) -> None:
523
+ """Add AI context to a command based on its purpose.
524
+
525
+ Args:
526
+ command: Command to enhance with AI context
527
+ """
528
+ if "test" in command.name:
529
+ self._add_test_ai_context(command)
530
+ elif "format" in command.name or "lint" in command.name:
531
+ self._add_quality_ai_context(command)
532
+
533
+ def _add_test_ai_context(self, command: CommandInfo) -> None:
534
+ """Add AI context for test-related commands."""
535
+ command.ai_context.update(
536
+ {
537
+ "purpose": "quality_assurance",
538
+ "automation_level": "high",
539
+ "ai_agent_compatible": True,
540
+ }
541
+ )
542
+ command.success_patterns.append("All tests passed")
543
+ command.failure_patterns.append("Test failures detected")
544
+
545
+ def _add_quality_ai_context(self, command: CommandInfo) -> None:
546
+ """Add AI context for code quality commands."""
547
+ command.ai_context.update(
548
+ {
549
+ "purpose": "code_quality",
550
+ "automation_level": "high",
551
+ "ai_agent_compatible": True,
552
+ }
553
+ )
554
+ command.success_patterns.append("No formatting issues")
555
+ command.failure_patterns.append("Style violations found")
556
+
557
+ def _categorize_commands(
558
+ self, commands: dict[str, CommandInfo]
559
+ ) -> dict[str, list[str]]:
560
+ """Categorize commands by purpose.
561
+
562
+ Args:
563
+ commands: Commands to categorize
564
+
565
+ Returns:
566
+ Dictionary of category to command names
567
+ """
568
+ categories: dict[str, list[str]] = {}
569
+ category_patterns = self._get_category_patterns()
570
+
571
+ for command in commands.values():
572
+ category = self._determine_command_category(command, category_patterns)
573
+ command.category = category
574
+ self._add_command_to_category(categories, category, command.name)
575
+
576
+ return categories
577
+
578
+ def _get_category_patterns(self) -> dict[str, list[str]]:
579
+ """Get category patterns for command classification."""
580
+ return {
581
+ "development": ["test", "format", "lint", "check", "run"],
582
+ "server": ["server", "start", "stop", "restart", "monitor"],
583
+ "release": ["version", "bump", "publish", "build", "tag"],
584
+ "configuration": ["config", "init", "setup", "install"],
585
+ "utilities": ["clean", "help", "info", "status"],
586
+ }
587
+
588
+ def _determine_command_category(
589
+ self, command: CommandInfo, category_patterns: dict[str, list[str]]
590
+ ) -> str:
591
+ """Determine the category for a command based on patterns."""
592
+ for category, patterns in category_patterns.items():
593
+ if any(pattern in command.name for pattern in patterns):
594
+ return category
595
+ return "general"
596
+
597
+ def _add_command_to_category(
598
+ self, categories: dict[str, list[str]], category: str, command_name: str
599
+ ) -> None:
600
+ """Add command to the specified category."""
601
+ if category not in categories:
602
+ categories[category] = []
603
+ categories[category].append(command_name)
604
+
605
+ def _generate_workflows(
606
+ self, commands: dict[str, CommandInfo]
607
+ ) -> dict[str, list[str]]:
608
+ """Generate workflow sequences from commands.
609
+
610
+ Args:
611
+ commands: Available commands
612
+
613
+ Returns:
614
+ Dictionary of workflow name to command sequence
615
+ """
616
+ workflows = {
617
+ "development_cycle": [
618
+ "format",
619
+ "lint",
620
+ "test",
621
+ "type-check",
622
+ ],
623
+ "release_cycle": [
624
+ "test",
625
+ "lint",
626
+ "version-bump",
627
+ "build",
628
+ "publish",
629
+ ],
630
+ "maintenance_cycle": [
631
+ "clean",
632
+ "update-dependencies",
633
+ "test",
634
+ "optimize",
635
+ ],
636
+ }
637
+
638
+ # Filter workflows to only include available commands
639
+ available_workflows = {}
640
+ for workflow_name, command_sequence in workflows.items():
641
+ available_sequence = [
642
+ cmd
643
+ for cmd in command_sequence
644
+ if any(cmd in available_cmd.name for available_cmd in commands.values())
645
+ ]
646
+ if available_sequence:
647
+ available_workflows[workflow_name] = available_sequence
648
+
649
+ return available_workflows
650
+
651
+ def _render_markdown(self, reference: CommandReference) -> str:
652
+ """Render reference as Markdown.
653
+
654
+ Args:
655
+ reference: Command reference
656
+
657
+ Returns:
658
+ Markdown formatted reference
659
+ """
660
+ lines = [
661
+ "# Command Reference",
662
+ "",
663
+ f"Generated: {reference.generated_at.strftime('%Y-%m-%d %H:%M:%S')}",
664
+ f"Version: {reference.version}",
665
+ "",
666
+ "## Categories",
667
+ "",
668
+ ]
669
+
670
+ # Add table of contents
671
+ lines.extend(self._render_markdown_toc(reference.categories))
672
+ lines.append("")
673
+
674
+ # Add commands by category
675
+ lines.extend(self._render_markdown_categories(reference))
676
+
677
+ # Add workflows if present
678
+ if reference.workflows:
679
+ lines.extend(self._render_markdown_workflows(reference.workflows))
680
+
681
+ return "\n".join(lines)
682
+
683
+ def _render_markdown_toc(self, categories: dict[str, list[str]]) -> list[str]:
684
+ """Render table of contents for markdown.
685
+
686
+ Args:
687
+ categories: Command categories
688
+
689
+ Returns:
690
+ List of TOC lines
691
+ """
692
+ return [
693
+ f"- [{category.title()}](#{category.replace('_', '-')})"
694
+ for category in categories
695
+ ]
696
+
697
+ def _render_markdown_categories(self, reference: CommandReference) -> list[str]:
698
+ """Render command categories for markdown."""
699
+ category_lines = []
700
+ for category, command_names in reference.categories.items():
701
+ category_section = self._render_markdown_category(
702
+ category, reference.commands, command_names
703
+ )
704
+ category_lines.extend(category_section)
705
+ return category_lines
706
+
707
+ def _render_markdown_category(
708
+ self, category: str, commands: dict[str, CommandInfo], command_names: list[str]
709
+ ) -> list[str]:
710
+ """Render markdown for a single category."""
711
+ category_lines = [
712
+ f"## {category.title()}",
713
+ "",
714
+ ]
715
+
716
+ for command_name in command_names:
717
+ command = commands[command_name]
718
+ command_lines = self._render_command_markdown(command)
719
+ category_lines.extend(command_lines)
720
+
721
+ return category_lines
722
+
723
+ def _render_markdown_workflows(self, workflows: dict[str, list[str]]) -> list[str]:
724
+ """Render workflows section for markdown.
725
+
726
+ Args:
727
+ workflows: Workflow definitions
728
+
729
+ Returns:
730
+ List of workflow section lines
731
+ """
732
+ workflow_lines = [
733
+ "## Workflows",
734
+ "",
735
+ ]
736
+
737
+ for workflow_name, command_sequence in workflows.items():
738
+ workflow_lines.extend(
739
+ [
740
+ f"### {workflow_name.replace('_', ' ').title()}",
741
+ "",
742
+ ]
743
+ )
744
+
745
+ for i, cmd in enumerate(command_sequence, 1):
746
+ workflow_lines.append(f"{i}. `{cmd}`")
747
+
748
+ workflow_lines.append("")
749
+
750
+ return workflow_lines
751
+
752
+ def _render_command_markdown(self, command: CommandInfo) -> list[str]:
753
+ """Render single command as Markdown."""
754
+ lines = [
755
+ f"### `{command.name}`",
756
+ "",
757
+ command.description,
758
+ "",
759
+ ]
760
+
761
+ # Add parameters section
762
+ if command.parameters:
763
+ param_lines = self._render_command_parameters_markdown(command.parameters)
764
+ lines.extend(param_lines)
765
+
766
+ # Add examples section
767
+ if command.examples:
768
+ example_lines = self._render_command_examples_markdown(command.examples)
769
+ lines.extend(example_lines)
770
+
771
+ # Add related commands section
772
+ if command.related_commands:
773
+ related_lines = self._render_command_related_markdown(
774
+ command.related_commands
775
+ )
776
+ lines.extend(related_lines)
777
+
778
+ return lines
779
+
780
+ def _render_command_parameters_markdown(
781
+ self, parameters: list[ParameterInfo]
782
+ ) -> list[str]:
783
+ """Render command parameters for markdown."""
784
+ param_lines = [
785
+ "**Parameters:**",
786
+ "",
787
+ ]
788
+
789
+ for param in parameters:
790
+ param_line = self._format_parameter_line(param)
791
+ param_lines.append(param_line)
792
+
793
+ param_lines.append("")
794
+ return param_lines
795
+
796
+ def _format_parameter_line(self, param: ParameterInfo) -> str:
797
+ """Format a single parameter line."""
798
+ required_str = " (required)" if param.required else ""
799
+ default_str = (
800
+ f" (default: {param.default_value})"
801
+ if param.default_value is not None
802
+ else ""
803
+ )
804
+ return f"- `--{param.name}` ({param.type_hint}){required_str}{default_str}: {param.description}"
805
+
806
+ def _render_command_examples_markdown(
807
+ self, examples: list[dict[str, str]]
808
+ ) -> list[str]:
809
+ """Render command examples for markdown.
810
+
811
+ Args:
812
+ examples: List of examples to render
813
+
814
+ Returns:
815
+ List of examples section lines
816
+ """
817
+ example_lines = [
818
+ "**Examples:**",
819
+ "",
820
+ ]
821
+
822
+ for example in examples:
823
+ example_lines.extend(
824
+ [
825
+ f"*{example['description']}:*",
826
+ "```bash",
827
+ example["command"],
828
+ "```",
829
+ "",
830
+ ]
831
+ )
832
+
833
+ return example_lines
834
+
835
+ def _render_command_related_markdown(
836
+ self, related_commands: list[str]
837
+ ) -> list[str]:
838
+ """Render related commands for markdown.
839
+
840
+ Args:
841
+ related_commands: List of related command names
842
+
843
+ Returns:
844
+ List of related commands section lines
845
+ """
846
+ return [
847
+ "**Related commands:** "
848
+ + ", ".join(f"`{cmd}`" for cmd in related_commands),
849
+ "",
850
+ ]
851
+
852
+ def _render_html(self, reference: CommandReference) -> str:
853
+ """Render reference as HTML."""
854
+ html_parts = [
855
+ self._render_html_header(
856
+ reference.generated_at.strftime("%Y-%m-%d %H:%M:%S")
857
+ ),
858
+ self._render_html_commands(reference),
859
+ "</body></html>",
860
+ ]
861
+ return "".join(html_parts)
862
+
863
+ def _render_html_header(self, generated_at: str) -> str:
864
+ """Render HTML header with styles and metadata."""
865
+ return f"""<!DOCTYPE html>
866
+ <html>
867
+ <head>
868
+ <title>Command Reference</title>
869
+ <style>
870
+ body {{ font-family: Arial, sans-serif; margin: 40px; }}
871
+ .command {{ margin-bottom: 2em; }}
872
+ .parameter {{ margin-left: 1em; }}
873
+ code {{ background-color: #f5f5f5; padding: 2px 4px; }}
874
+ pre {{ background-color: #f5f5f5; padding: 10px; }}
875
+ </style>
876
+ </head>
877
+ <body>
878
+ <h1>Command Reference</h1>
879
+ <p>Generated: {generated_at}</p>
880
+ """
881
+
882
+ def _render_html_commands(self, reference: CommandReference) -> str:
883
+ """Render HTML commands by category."""
884
+ html_parts = []
885
+ for category, command_names in reference.categories.items():
886
+ category_html = self._render_html_category(
887
+ category, reference.commands, command_names
888
+ )
889
+ html_parts.append(category_html)
890
+ return "".join(html_parts)
891
+
892
+ def _render_html_category(
893
+ self, category: str, commands: dict[str, CommandInfo], command_names: list[str]
894
+ ) -> str:
895
+ """Render HTML for a single category."""
896
+ html = f"<h2>{category.title()}</h2>"
897
+ html += self._render_html_category_commands(commands, command_names)
898
+ return html
899
+
900
+ def _render_html_category_commands(
901
+ self, commands: dict[str, CommandInfo], command_names: list[str]
902
+ ) -> str:
903
+ """Render HTML for commands in a category."""
904
+ html_parts = []
905
+ for command_name in command_names:
906
+ command = commands[command_name]
907
+ command_html = self._render_single_html_command(command)
908
+ html_parts.append(command_html)
909
+ return "".join(html_parts)
910
+
911
+ def _render_single_html_command(self, command: CommandInfo) -> str:
912
+ """Render HTML for a single command."""
913
+ html = '<div class="command">'
914
+ html += f"<h3><code>{command.name}</code></h3>"
915
+ html += f"<p>{command.description}</p>"
916
+ html += self._render_html_command_parameters(command.parameters)
917
+ html += "</div>"
918
+ return html
919
+
920
+ def _render_html_command_parameters(self, parameters: list[ParameterInfo]) -> str:
921
+ """Render HTML for command parameters."""
922
+ if not parameters:
923
+ return ""
924
+
925
+ html = "<h4>Parameters:</h4><ul>"
926
+ for param in parameters:
927
+ html += f'<li class="parameter"><code>--{param.name}</code> ({param.type_hint}): {param.description}</li>'
928
+ html += "</ul>"
929
+ return html
930
+
931
+ def _render_json(self, reference: CommandReference) -> str:
932
+ """Render reference as JSON."""
933
+ import json
934
+
935
+ data: dict[str, t.Any] = {
936
+ "generated_at": reference.generated_at.isoformat(),
937
+ "version": reference.version,
938
+ "categories": reference.categories,
939
+ "workflows": reference.workflows,
940
+ "commands": self._serialize_commands(reference.commands),
941
+ }
942
+
943
+ return json.dumps(data, indent=2, default=str)
944
+
945
+ def _serialize_commands(self, commands: dict[str, CommandInfo]) -> dict[str, t.Any]:
946
+ """Serialize commands for JSON output."""
947
+ serialized_commands = {}
948
+ for name, command in commands.items():
949
+ serialized_commands[name] = self._serialize_command(command)
950
+ return serialized_commands
951
+
952
+ def _serialize_command(self, command: CommandInfo) -> dict[str, t.Any]:
953
+ """Serialize a single command for JSON output."""
954
+ return {
955
+ "name": command.name,
956
+ "description": command.description,
957
+ "category": command.category,
958
+ "parameters": self._serialize_parameters(command.parameters),
959
+ "examples": command.examples,
960
+ "related_commands": command.related_commands,
961
+ "aliases": command.aliases,
962
+ }
963
+
964
+ def _serialize_parameters(
965
+ self, parameters: list[ParameterInfo]
966
+ ) -> list[dict[str, t.Any]]:
967
+ """Serialize parameters for JSON output."""
968
+ return [self._serialize_parameter(param) for param in parameters]
969
+
970
+ def _serialize_parameter(self, param: ParameterInfo) -> dict[str, t.Any]:
971
+ """Serialize a single parameter for JSON output."""
972
+ return {
973
+ "name": param.name,
974
+ "type": param.type_hint,
975
+ "default": param.default_value,
976
+ "description": param.description,
977
+ "required": param.required,
978
+ }
979
+
980
+ def _render_yaml(self, reference: CommandReference) -> str:
981
+ """Render reference as YAML."""
982
+ import yaml
983
+
984
+ # Convert to JSON-serializable format first
985
+ json_data = self._render_json(reference)
986
+ import json
987
+
988
+ data = json.loads(json_data)
989
+
990
+ return yaml.dump(data, default_flow_style=False, sort_keys=False)
991
+
992
+ def _render_rst(self, reference: CommandReference) -> str:
993
+ """Render reference as reStructuredText."""
994
+ lines = [
995
+ "Command Reference",
996
+ "=================",
997
+ "",
998
+ f"Generated: {reference.generated_at.strftime('%Y-%m-%d %H:%M:%S')}",
999
+ f"Version: {reference.version}",
1000
+ "",
1001
+ ]
1002
+
1003
+ lines.extend(self._render_rst_categories(reference))
1004
+ return "\n".join(lines)
1005
+
1006
+ def _render_rst_categories(self, reference: CommandReference) -> list[str]:
1007
+ """Render RST categories and commands."""
1008
+ rst_lines = []
1009
+
1010
+ for category, command_names in reference.categories.items():
1011
+ rst_lines.extend(
1012
+ [
1013
+ category.title(),
1014
+ "-" * len(category),
1015
+ "",
1016
+ ]
1017
+ )
1018
+
1019
+ rst_lines.extend(
1020
+ self._render_rst_category_commands(reference.commands, command_names)
1021
+ )
1022
+
1023
+ return rst_lines
1024
+
1025
+ def _render_rst_category_commands(
1026
+ self, commands: dict[str, CommandInfo], command_names: list[str]
1027
+ ) -> list[str]:
1028
+ """Render RST commands for a category."""
1029
+ command_lines = []
1030
+
1031
+ for command_name in command_names:
1032
+ command = commands[command_name]
1033
+ command_lines.extend(
1034
+ [
1035
+ f"``{command.name}``",
1036
+ "^" * (len(command.name) + 4),
1037
+ "",
1038
+ command.description,
1039
+ "",
1040
+ ]
1041
+ )
1042
+
1043
+ if command.parameters:
1044
+ command_lines.extend(
1045
+ self._render_rst_command_parameters(command.parameters)
1046
+ )
1047
+
1048
+ return command_lines
1049
+
1050
+ def _render_rst_command_parameters(
1051
+ self, parameters: list[ParameterInfo]
1052
+ ) -> list[str]:
1053
+ """Render RST command parameters."""
1054
+ param_lines = [
1055
+ "Parameters:",
1056
+ "",
1057
+ ]
1058
+
1059
+ for param in parameters:
1060
+ param_lines.append(
1061
+ f"* ``--{param.name}`` ({param.type_hint}): {param.description}"
1062
+ )
1063
+
1064
+ param_lines.append("")
1065
+ return param_lines