crackerjack 0.32.0__py3-none-any.whl → 0.33.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (200) hide show
  1. crackerjack/__main__.py +1350 -34
  2. crackerjack/adapters/__init__.py +17 -0
  3. crackerjack/adapters/lsp_client.py +358 -0
  4. crackerjack/adapters/rust_tool_adapter.py +194 -0
  5. crackerjack/adapters/rust_tool_manager.py +193 -0
  6. crackerjack/adapters/skylos_adapter.py +231 -0
  7. crackerjack/adapters/zuban_adapter.py +560 -0
  8. crackerjack/agents/base.py +7 -3
  9. crackerjack/agents/coordinator.py +271 -33
  10. crackerjack/agents/documentation_agent.py +9 -15
  11. crackerjack/agents/dry_agent.py +3 -15
  12. crackerjack/agents/formatting_agent.py +1 -1
  13. crackerjack/agents/import_optimization_agent.py +36 -180
  14. crackerjack/agents/performance_agent.py +17 -98
  15. crackerjack/agents/performance_helpers.py +7 -31
  16. crackerjack/agents/proactive_agent.py +1 -3
  17. crackerjack/agents/refactoring_agent.py +16 -85
  18. crackerjack/agents/refactoring_helpers.py +7 -42
  19. crackerjack/agents/security_agent.py +9 -48
  20. crackerjack/agents/test_creation_agent.py +356 -513
  21. crackerjack/agents/test_specialist_agent.py +0 -4
  22. crackerjack/api.py +6 -25
  23. crackerjack/cli/cache_handlers.py +204 -0
  24. crackerjack/cli/cache_handlers_enhanced.py +683 -0
  25. crackerjack/cli/facade.py +100 -0
  26. crackerjack/cli/handlers.py +224 -9
  27. crackerjack/cli/interactive.py +6 -4
  28. crackerjack/cli/options.py +642 -55
  29. crackerjack/cli/utils.py +2 -1
  30. crackerjack/code_cleaner.py +58 -117
  31. crackerjack/config/global_lock_config.py +8 -48
  32. crackerjack/config/hooks.py +53 -62
  33. crackerjack/core/async_workflow_orchestrator.py +24 -34
  34. crackerjack/core/autofix_coordinator.py +3 -17
  35. crackerjack/core/enhanced_container.py +64 -6
  36. crackerjack/core/file_lifecycle.py +12 -89
  37. crackerjack/core/performance.py +2 -2
  38. crackerjack/core/performance_monitor.py +15 -55
  39. crackerjack/core/phase_coordinator.py +257 -218
  40. crackerjack/core/resource_manager.py +14 -90
  41. crackerjack/core/service_watchdog.py +62 -95
  42. crackerjack/core/session_coordinator.py +149 -0
  43. crackerjack/core/timeout_manager.py +14 -72
  44. crackerjack/core/websocket_lifecycle.py +13 -78
  45. crackerjack/core/workflow_orchestrator.py +558 -240
  46. crackerjack/docs/INDEX.md +11 -0
  47. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  48. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  49. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  50. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  51. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  52. crackerjack/documentation/__init__.py +31 -0
  53. crackerjack/documentation/ai_templates.py +756 -0
  54. crackerjack/documentation/dual_output_generator.py +765 -0
  55. crackerjack/documentation/mkdocs_integration.py +518 -0
  56. crackerjack/documentation/reference_generator.py +977 -0
  57. crackerjack/dynamic_config.py +55 -50
  58. crackerjack/executors/async_hook_executor.py +10 -15
  59. crackerjack/executors/cached_hook_executor.py +117 -43
  60. crackerjack/executors/hook_executor.py +8 -34
  61. crackerjack/executors/hook_lock_manager.py +26 -183
  62. crackerjack/executors/individual_hook_executor.py +13 -11
  63. crackerjack/executors/lsp_aware_hook_executor.py +270 -0
  64. crackerjack/executors/tool_proxy.py +417 -0
  65. crackerjack/hooks/lsp_hook.py +79 -0
  66. crackerjack/intelligence/adaptive_learning.py +25 -10
  67. crackerjack/intelligence/agent_orchestrator.py +2 -5
  68. crackerjack/intelligence/agent_registry.py +34 -24
  69. crackerjack/intelligence/agent_selector.py +5 -7
  70. crackerjack/interactive.py +17 -6
  71. crackerjack/managers/async_hook_manager.py +0 -1
  72. crackerjack/managers/hook_manager.py +79 -1
  73. crackerjack/managers/publish_manager.py +66 -13
  74. crackerjack/managers/test_command_builder.py +5 -17
  75. crackerjack/managers/test_executor.py +1 -3
  76. crackerjack/managers/test_manager.py +109 -7
  77. crackerjack/managers/test_manager_backup.py +10 -9
  78. crackerjack/mcp/cache.py +2 -2
  79. crackerjack/mcp/client_runner.py +1 -1
  80. crackerjack/mcp/context.py +191 -68
  81. crackerjack/mcp/dashboard.py +7 -5
  82. crackerjack/mcp/enhanced_progress_monitor.py +31 -28
  83. crackerjack/mcp/file_monitor.py +30 -23
  84. crackerjack/mcp/progress_components.py +31 -21
  85. crackerjack/mcp/progress_monitor.py +50 -53
  86. crackerjack/mcp/rate_limiter.py +6 -6
  87. crackerjack/mcp/server_core.py +161 -32
  88. crackerjack/mcp/service_watchdog.py +2 -1
  89. crackerjack/mcp/state.py +4 -7
  90. crackerjack/mcp/task_manager.py +11 -9
  91. crackerjack/mcp/tools/core_tools.py +174 -33
  92. crackerjack/mcp/tools/error_analyzer.py +3 -2
  93. crackerjack/mcp/tools/execution_tools.py +15 -12
  94. crackerjack/mcp/tools/execution_tools_backup.py +42 -30
  95. crackerjack/mcp/tools/intelligence_tool_registry.py +7 -5
  96. crackerjack/mcp/tools/intelligence_tools.py +5 -2
  97. crackerjack/mcp/tools/monitoring_tools.py +33 -70
  98. crackerjack/mcp/tools/proactive_tools.py +24 -11
  99. crackerjack/mcp/tools/progress_tools.py +5 -8
  100. crackerjack/mcp/tools/utility_tools.py +20 -14
  101. crackerjack/mcp/tools/workflow_executor.py +62 -40
  102. crackerjack/mcp/websocket/app.py +8 -0
  103. crackerjack/mcp/websocket/endpoints.py +352 -357
  104. crackerjack/mcp/websocket/jobs.py +40 -57
  105. crackerjack/mcp/websocket/monitoring_endpoints.py +2935 -0
  106. crackerjack/mcp/websocket/server.py +7 -25
  107. crackerjack/mcp/websocket/websocket_handler.py +6 -17
  108. crackerjack/mixins/__init__.py +3 -0
  109. crackerjack/mixins/error_handling.py +145 -0
  110. crackerjack/models/config.py +21 -1
  111. crackerjack/models/config_adapter.py +49 -1
  112. crackerjack/models/protocols.py +176 -107
  113. crackerjack/models/resource_protocols.py +55 -210
  114. crackerjack/models/task.py +3 -0
  115. crackerjack/monitoring/ai_agent_watchdog.py +13 -13
  116. crackerjack/monitoring/metrics_collector.py +426 -0
  117. crackerjack/monitoring/regression_prevention.py +8 -8
  118. crackerjack/monitoring/websocket_server.py +643 -0
  119. crackerjack/orchestration/advanced_orchestrator.py +11 -6
  120. crackerjack/orchestration/coverage_improvement.py +3 -3
  121. crackerjack/orchestration/execution_strategies.py +26 -6
  122. crackerjack/orchestration/test_progress_streamer.py +8 -5
  123. crackerjack/plugins/base.py +2 -2
  124. crackerjack/plugins/hooks.py +7 -0
  125. crackerjack/plugins/managers.py +11 -8
  126. crackerjack/security/__init__.py +0 -1
  127. crackerjack/security/audit.py +90 -105
  128. crackerjack/services/anomaly_detector.py +392 -0
  129. crackerjack/services/api_extractor.py +615 -0
  130. crackerjack/services/backup_service.py +2 -2
  131. crackerjack/services/bounded_status_operations.py +15 -152
  132. crackerjack/services/cache.py +127 -1
  133. crackerjack/services/changelog_automation.py +395 -0
  134. crackerjack/services/config.py +18 -11
  135. crackerjack/services/config_merge.py +30 -85
  136. crackerjack/services/config_template.py +506 -0
  137. crackerjack/services/contextual_ai_assistant.py +48 -22
  138. crackerjack/services/coverage_badge_service.py +171 -0
  139. crackerjack/services/coverage_ratchet.py +41 -17
  140. crackerjack/services/debug.py +3 -3
  141. crackerjack/services/dependency_analyzer.py +460 -0
  142. crackerjack/services/dependency_monitor.py +14 -11
  143. crackerjack/services/documentation_generator.py +491 -0
  144. crackerjack/services/documentation_service.py +675 -0
  145. crackerjack/services/enhanced_filesystem.py +6 -5
  146. crackerjack/services/enterprise_optimizer.py +865 -0
  147. crackerjack/services/error_pattern_analyzer.py +676 -0
  148. crackerjack/services/file_hasher.py +1 -1
  149. crackerjack/services/git.py +41 -45
  150. crackerjack/services/health_metrics.py +10 -8
  151. crackerjack/services/heatmap_generator.py +735 -0
  152. crackerjack/services/initialization.py +30 -33
  153. crackerjack/services/input_validator.py +5 -97
  154. crackerjack/services/intelligent_commit.py +327 -0
  155. crackerjack/services/log_manager.py +15 -12
  156. crackerjack/services/logging.py +4 -3
  157. crackerjack/services/lsp_client.py +628 -0
  158. crackerjack/services/memory_optimizer.py +409 -0
  159. crackerjack/services/metrics.py +42 -33
  160. crackerjack/services/parallel_executor.py +416 -0
  161. crackerjack/services/pattern_cache.py +1 -1
  162. crackerjack/services/pattern_detector.py +6 -6
  163. crackerjack/services/performance_benchmarks.py +250 -576
  164. crackerjack/services/performance_cache.py +382 -0
  165. crackerjack/services/performance_monitor.py +565 -0
  166. crackerjack/services/predictive_analytics.py +510 -0
  167. crackerjack/services/quality_baseline.py +234 -0
  168. crackerjack/services/quality_baseline_enhanced.py +646 -0
  169. crackerjack/services/quality_intelligence.py +785 -0
  170. crackerjack/services/regex_patterns.py +605 -524
  171. crackerjack/services/regex_utils.py +43 -123
  172. crackerjack/services/secure_path_utils.py +5 -164
  173. crackerjack/services/secure_status_formatter.py +30 -141
  174. crackerjack/services/secure_subprocess.py +11 -92
  175. crackerjack/services/security.py +61 -30
  176. crackerjack/services/security_logger.py +18 -22
  177. crackerjack/services/server_manager.py +124 -16
  178. crackerjack/services/status_authentication.py +16 -159
  179. crackerjack/services/status_security_manager.py +4 -131
  180. crackerjack/services/terminal_utils.py +0 -0
  181. crackerjack/services/thread_safe_status_collector.py +19 -125
  182. crackerjack/services/unified_config.py +21 -13
  183. crackerjack/services/validation_rate_limiter.py +5 -54
  184. crackerjack/services/version_analyzer.py +459 -0
  185. crackerjack/services/version_checker.py +1 -1
  186. crackerjack/services/websocket_resource_limiter.py +10 -144
  187. crackerjack/services/zuban_lsp_service.py +390 -0
  188. crackerjack/slash_commands/__init__.py +2 -7
  189. crackerjack/slash_commands/run.md +2 -2
  190. crackerjack/tools/validate_input_validator_patterns.py +14 -40
  191. crackerjack/tools/validate_regex_patterns.py +19 -48
  192. {crackerjack-0.32.0.dist-info → crackerjack-0.33.1.dist-info}/METADATA +197 -26
  193. crackerjack-0.33.1.dist-info/RECORD +229 -0
  194. crackerjack/CLAUDE.md +0 -207
  195. crackerjack/RULES.md +0 -380
  196. crackerjack/py313.py +0 -234
  197. crackerjack-0.32.0.dist-info/RECORD +0 -180
  198. {crackerjack-0.32.0.dist-info → crackerjack-0.33.1.dist-info}/WHEEL +0 -0
  199. {crackerjack-0.32.0.dist-info → crackerjack-0.33.1.dist-info}/entry_points.txt +0 -0
  200. {crackerjack-0.32.0.dist-info → crackerjack-0.33.1.dist-info}/licenses/LICENSE +0 -0
crackerjack/RULES.md DELETED
@@ -1,380 +0,0 @@
1
- # Crackerjack Style Rules
2
-
3
- ## Clean Code Philosophy (Foundation)
4
-
5
- **EVERY LINE OF CODE IS A LIABILITY. The best code is no code.**
6
-
7
- - **DRY (Don't Repeat Yourself)**: If you write it twice, you're doing it wrong
8
- - **YAGNI (You Ain't Gonna Need It)**: Build only what's needed NOW
9
- - **KISS (Keep It Simple, Stupid)**: Complexity is the enemy of maintainability
10
- - **Less is More**: Prefer 10 lines that are clear over 100 that are clever
11
- - **Code is Read 10x More Than Written**: Optimize for readability
12
- - **Self-Documenting Code**: Code should explain itself; comments only for "why", not "what". Variable names should **ALWAYS** be clear and descriptive, even in inline map/filter functions.
13
-
14
- ## Code Quality & Style
15
-
16
- - **Use Static Typing Everywhere**
17
-
18
- - Always include comprehensive type hints
19
- - Use modern typing syntax with the pipe operator (`|`) for unions instead of `Optional[T]`
20
- - Import typing as `import typing as t` and prefix all typing references with `t.`
21
- - Never import individual types directly from typing (e.g., avoid `from typing import List, Dict, Optional`)
22
- - Always use the `t.` prefix for all typing-related types
23
- - Use built-in collection types directly instead of typing equivalents:
24
- - Use `list[str]` instead of `t.List[str]`
25
- - Use `dict[str, int]` instead of `t.Dict[str, int]`
26
- - Use `tuple[int, ...]` instead of `t.Tuple[int, ...]`
27
-
28
- - **Modern Python Features**
29
-
30
- - Target Python 3.13+ features and syntax
31
- - Use f-strings instead of other string formatting methods
32
- - Prefer `pathlib.Path` over `os.path` for file operations
33
-
34
- - **Clean Code Architecture**
35
-
36
- - Write modular functions that do one thing well
37
- - **NO DOCSTRINGS**: Never add docstrings to any code - the codebase standard is to have no docstrings (they are automatically removed by the `-x` flag)
38
- - Avoid unnecessary line comments - use them sparingly only for complex logic
39
- - Use protocols (`t.Protocol`) instead of abstract base classes
40
- - Choose clear, descriptive variable and function names that make the code self-documenting (even in map/filter functions)
41
- - **Keep cognitive complexity ≤15 per function** - extract helper methods if needed (KISS principle)
42
-
43
- - **Code Organization**
44
-
45
- - Group related functionality into well-defined classes
46
- - Use runtime-checkable protocols with `@t.runtime_checkable`
47
- - Prefer dataclasses for structured data
48
- - Use type checking with strict enforcement
49
-
50
- - **Project Structure**
51
-
52
- - Structure projects with clear separation of concerns
53
- - Follow standard package layout conventions
54
- - Use [pyproject.toml](https://github.com/lesleslie/crackerjack/blob/main/pyproject.toml) for all configuration
55
- - **Modular Architecture**: Use protocol-based dependency injection
56
- - Core orchestration layer: `WorkflowOrchestrator`, `AsyncWorkflowOrchestrator`
57
- - Coordinator layer: `SessionCoordinator`, `PhaseCoordinator`
58
- - Domain managers: `HookManager`, `TestManager`, `PublishManager`
59
- - Infrastructure services: filesystem, git, config, security
60
-
61
- ## Tool Integration
62
-
63
- - **Integrate with Quality Tools**
64
-
65
- - Configure code with Ruff for linting and formatting
66
- - Set up pre-commit hooks for consistent code quality
67
- - Use UV for dependency management
68
-
69
- ## Critical Error Prevention
70
-
71
- **Bandit B108 (Hardcoded Temp Directory):**
72
-
73
- ```python
74
- # NEVER do this - causes security warnings
75
- config_path = "/tmp/test-config.yaml"
76
-
77
- # ALWAYS use tempfile module
78
- import tempfile
79
-
80
- with tempfile.NamedTemporaryFile(suffix=".yaml", delete=False) as temp_file:
81
- config_path = temp_file.name
82
- ```
83
-
84
- **Refurb FURB184 (Return Statement Chaining):**
85
-
86
- ```python
87
- # AVOID - unnecessary intermediate variable
88
- def create_config() -> Config:
89
- generator = ConfigGenerator()
90
- return generator.create_config()
91
-
92
-
93
- # PREFER - chained return statement
94
- def create_config() -> Config:
95
- return ConfigGenerator().create_config()
96
- ```
97
-
98
- **Pyright Protocol Compatibility:**
99
-
100
- ```python
101
- # ALWAYS implement ALL protocol properties
102
- class TestOptions(OptionsProtocol):
103
- # Missing properties cause type errors
104
- verbose: bool = False
105
- experimental_hooks: bool = False # Don't forget new properties
106
- enable_pyrefly: bool = False
107
- enable_ty: bool = False
108
- compress_docs: bool = False
109
- ```
110
-
111
- **Complexipy Complexity (>15):**
112
-
113
- ```python
114
- # AVOID - high complexity method
115
- def process_data(self, data: dict) -> Result:
116
- if condition1:
117
- if condition2:
118
- if condition3:
119
- pass # ... many nested conditions >15 complexity
120
-
121
-
122
- # PREFER - extracted helper methods
123
- def process_data(self, data: dict) -> Result:
124
- if self._should_process(data):
125
- return self._handle_processing(data)
126
- return self._handle_error(data)
127
-
128
-
129
- def _should_process(self, data: dict) -> bool:
130
- return condition1 and condition2 and condition3
131
- ```
132
-
133
- - Implement pytest for testing with timeout handling
134
-
135
- - **Use UV for Tool Execution**
136
-
137
- - Always use `uv run` to execute tools within the project's virtual environment
138
- - Run pytest with `uv run pytest` instead of calling pytest directly
139
- - Execute tools like pyright, ruff, and crackerjack through UV: `uv run pyright`
140
- - Ensures consistent tool versions and environment isolation
141
-
142
- - **Pre-Commit Hook Configuration**
143
-
144
- - Enforce a comprehensive set of pre-commit hooks for quality control:
145
- - Pyright for static type checking
146
- - Ruff for linting and formatting
147
- - Vulture for detecting unused code
148
- - Creosote for identifying unused dependencies
149
- - Complexipy for code complexity analysis
150
- - Codespell for spell checking
151
- - Autotyping for type annotation
152
- - Refurb for Python code modernization
153
- - Bandit for security vulnerabilities
154
- - Run hooks with `uv run pre-commit run --all-files` during development
155
- - Configure hooks in `.pre-commit-config.yaml` with exact versions
156
- - Ensure all code passes pre-commit checks before submitting
157
-
158
- - **Specific Tool Compliance Standards**
159
-
160
- - **Refurb (FURB Rules):**
161
-
162
- - **FURB109**: ALWAYS use tuples `()` instead of lists `[]` for `in` membership testing
163
- - **FURB120**: Never pass default values that match the function's default (e.g., `None` for optional parameters)
164
- - Use modern Python patterns and built-ins consistently
165
-
166
- - **Pyright Type Checking:**
167
-
168
- - **reportMissingParameterType**: ALL function parameters MUST have complete type annotations
169
- - **reportArgumentType**: Protocol implementations must include ALL required properties with correct types
170
- - Use explicit type annotations for all function parameters and return types
171
-
172
- - **Complexipy Code Complexity (KISS Enforcement):**
173
-
174
- - Keep cognitive complexity ≤15 per function/method
175
- - Break complex methods into 3-5 smaller helper functions with single responsibilities
176
- - Use descriptive function names that explain their purpose
177
- - Remember: complexity is the enemy of maintainability
178
-
179
- - **Bandit Security:**
180
-
181
- - Never use dangerous functions like `eval()`, `exec()`, or `subprocess.shell=True`
182
- - Use `secrets` module for cryptographic operations, never `random`
183
- - Always specify encoding when opening files
184
-
185
- - **Automation Focus**
186
-
187
- - Automate repetitive tasks whenever possible
188
- - Create helpers for common development workflows
189
- - Implement consistent error handling and reporting
190
-
191
- ## Development Philosophy
192
-
193
- Following our **Clean Code Philosophy** where every line of code is a liability:
194
-
195
- - **Simplicity Over Cleverness** (KISS)
196
-
197
- - Choose obvious solutions over clever ones
198
- - Prefer explicit code over implicit magic
199
- - Write code that junior developers can understand
200
-
201
- - **Build Only What's Needed** (YAGNI)
202
-
203
- - Implement current requirements, not future possibilities
204
- - Remove dead code immediately when discovered
205
- - Resist over-engineering and premature optimization
206
-
207
- - **Eliminate Repetition** (DRY)
208
-
209
- - Extract common patterns into reusable functions
210
- - Create shared utilities for repeated operations
211
- - Use protocols and interfaces to reduce duplication
212
-
213
- - **Consistency is Key**
214
-
215
- - Maintain uniform style across the entire codebase
216
- - Standardize import order and grouping
217
- - Keep a consistent approach to error handling
218
-
219
- - **Reliability and Testing**
220
-
221
- - Write comprehensive tests using pytest
222
- - Add appropriate timeouts to prevent hanging tests
223
- - Use parallel test execution when appropriate
224
- - Never create files directly on the filesystem in tests
225
- - Always use `tempfile` module for temporary files and directories
226
- - Use pytest's `tmp_path` and `tmp_path_factory` fixtures
227
- - Clean up any generated resources after tests complete
228
- - Tests should be isolated and not affect the surrounding environment
229
- - Avoid hard-coded paths in tests that point to the real filesystem
230
-
231
- - **Code Quality Validation**
232
-
233
- - Code should pass all quality checks when run through crackerjack
234
- - The ultimate goal is to run `python -m crackerjack -x -t` without any errors
235
- - This validates proper typing, formatting, linting, and test success
236
- - Consider code incomplete until it passes this validation
237
-
238
- - **Error Handling**
239
-
240
- - Use structured exception handling with specific exception types
241
- - Provide meaningful error messages
242
- - Add appropriate error context for debugging
243
-
244
- - **Rich Output**
245
-
246
- - Use the Rich library for console output
247
- - Provide clear status indicators for operations
248
- - Format output for readability
249
-
250
- - **Opinionated Choices**
251
-
252
- - Enforce a single correct way to accomplish tasks
253
- - Remove unnecessary flexibility that could lead to inconsistency
254
- - Value clarity over brevity
255
-
256
- ## Additional Best Practices
257
-
258
- - **Performance Considerations**
259
-
260
- - Use profiling tools to identify bottlenecks in critical code paths
261
- - Benchmark and compare alternative implementations for optimization
262
- - Favor readability over micro-optimizations except for demonstrated hot spots
263
- - Document any non-obvious optimizations with comments explaining the rationale
264
-
265
- - **Python Version Strategy**
266
-
267
- - Target only the latest stable Python release (3.13+)
268
- - Adopt new language features as soon as they become available
269
- - Do not maintain backward compatibility with older Python versions
270
- - Regularly update codebases to take advantage of new language improvements
271
- - Plan to upgrade within weeks of a new Python release
272
-
273
- - **Documentation Minimalism**
274
-
275
- - Keep documentation focused on "why" rather than "what" the code does
276
- - Document APIs at the module or class level rather than individual functions
277
- - Use type hints to replace most parameter documentation
278
- - Create examples for complex functionality instead of verbose explanations
279
-
280
- - **Testing Philosophy**
281
-
282
- - Write tests for behavior, not implementation details
283
- - Focus on testing public interfaces rather than private functions
284
- - Use property-based testing for algorithmic code where appropriate
285
- - Separate unit tests, integration tests, and benchmarks
286
- - Aim for complete test coverage of critical paths but avoid test-for-test's-sake
287
- - Use asyncio exclusively for async testing; do not test with trio compatibility
288
- - Configure pytest with asyncio_mode="auto" for simpler async testing
289
-
290
- - **Test Coverage Improvement (MANDATORY)**
291
-
292
- - **Maintain 42% minimum coverage**: Never reduce coverage below 42% in config files
293
- - **Always improve coverage incrementally** when working on projects with pytest coverage below the target
294
- - **Check coverage first**: Run `uv run pytest --cov=<package_name> --cov-report=term-missing` to see current status
295
- - **Target 2-5% improvement per session**: Add 1-3 focused tests that cover uncovered lines
296
- - **Prioritize easy wins**: Test simple functions, error paths, edge cases, and validation logic
297
- - **3-attempt rule**: If a test doesn't work after 3 debugging attempts, skip it and move on
298
- - **Time-boxed effort**: Spend maximum 10-15 minutes on coverage improvement per session
299
- - **Focus on low-hanging fruit**: Property getters, simple validation, string formatting, error handling
300
- - **Avoid complex coverage improvements**: Skip async operations, external integrations, and complex state management
301
- - **Write focused tests**: Each test should cover 1-3 lines of uncovered code
302
- - **Quality over quantity**: Tests should be simple, reliable, and fast (< 1 second each)
303
- - **Example incremental approach**:
304
- ```python
305
- # Target: Cover error handling in Options validation
306
- def test_options_invalid_bump_option():
307
- with pytest.raises(ValueError, match="Invalid bump option"):
308
- Options(publish="invalid")
309
-
310
-
311
- # Target: Cover string representation
312
- def test_bump_option_str():
313
- assert str(BumpOption.patch) == "patch"
314
-
315
-
316
- # Target: Cover edge case in validation
317
- def test_validate_empty_string():
318
- result = Options.validate_bump_options("")
319
- assert result == BumpOption.interactive
320
- ```
321
-
322
- - **Dependency Management**
323
-
324
- - Keep external dependencies to a minimum
325
- - Pin exact versions in lockfiles but use range specifications in pyproject.toml
326
- - Regularly audit dependencies for security issues
327
- - Prefer standard library solutions when reasonable
328
- - Favor dependencies that support the latest Python version
329
-
330
- - **Code Review Standards**
331
-
332
- - All code should be reviewed before merging
333
- - Automate style and formatting checks to focus reviews on substance
334
- - Look for edge cases and error handling in reviews
335
- - Ensure tests adequately cover the changes
336
-
337
- - **Session Progress Tracking**
338
-
339
- - Progress tracking is now handled automatically by the MCP WebSocket server
340
- - Real-time progress monitoring available at `ws://localhost:8675`
341
- - Use `--resume-from` to continue interrupted sessions rather than starting over
342
-
343
- ## AI Agent Integration
344
-
345
- - **AI Agent Iteration Workflow (CRITICAL)**
346
-
347
- - AI agent mode (`--ai-agent`) follows strict iteration protocol:
348
- 1. **Fast Hooks** → Retry once if any fail (formatting fixes often cascade)
349
- 1. **Collect ALL Test Failures** → Don't stop on first failure, gather complete list
350
- 1. **Collect ALL Hook Issues** → Don't stop on first failure, gather complete list
351
- 1. **Apply AI Fixes** → Process ALL collected issues in batch, then move to next iteration
352
- - **CRITICAL**: AI agent only advances to next iteration AFTER applying fixes
353
- - This ensures each iteration validates fixes from the previous iteration
354
- - Maximum 10 iterations to prevent infinite loops
355
- - AsyncWorkflowOrchestrator implements this logic for MCP server compatibility
356
-
357
- - **MCP Server Integration**
358
-
359
- - Use standard orchestrator for MCP compatibility (not advanced orchestrator)
360
- - WebSocket progress reporting requires proper iteration boundaries
361
- - Real-time progress available at `ws://localhost:8675/ws/progress/{job_id}`
362
- - MCP tools: `execute_crackerjack`, `get_job_progress`, `get_comprehensive_status`
363
-
364
- ## AI Assistant Self-Maintenance
365
-
366
- - **Quality Standards Maintenance**
367
-
368
- - AI assistants should update CLAUDE.md and RULES.md weekly or after pre-commit failures
369
- - Learn from new Refurb rules (FURB codes), Pyright errors (reportXxx), and Complexipy thresholds
370
- - Add newly discovered error patterns to documentation with code examples
371
- - Test all documentation updates by running `python -m crackerjack --comprehensive`
372
- - Prioritize frequently occurring error patterns as **CRITICAL** standards
373
-
374
- - **Self-Learning Protocol**
375
-
376
- - When encountering new pre-commit failures, extract the error pattern and add to standards
377
- - Format new patterns with "Bad" and "Good" code examples
378
- - Update the "AI Code Generation Best Practices" checklist in CLAUDE.md
379
- - Ensure RULES.md stays synchronized with CLAUDE.md standards
380
- - Monitor tool version updates and incorporate new rules as they emerge
crackerjack/py313.py DELETED
@@ -1,234 +0,0 @@
1
- import subprocess
2
- import typing
3
- from enum import Enum, auto
4
- from pathlib import Path
5
- from typing import Any, Self, TypedDict
6
-
7
-
8
- class CommandRunner[TReturn]:
9
- def run_command(self, cmd: list[str], **kwargs: Any) -> TReturn: ...
10
-
11
-
12
- class CommandResult(TypedDict):
13
- success: bool
14
- exit_code: int
15
- stdout: str
16
- stderr: str
17
- command: list[str]
18
- duration_ms: float
19
-
20
-
21
- def process_command_output(result: CommandResult) -> tuple[bool, str]:
22
- match result:
23
- case {"success": True, "stdout": stdout} if stdout.strip():
24
- return (True, stdout)
25
- case {"success": True}:
26
- return (True, "Command completed successfully with no output")
27
- case {"success": False, "exit_code": code, "stderr": stderr} if code == 127:
28
- return (False, f"Command not found: {stderr}")
29
- case {"success": False, "exit_code": code} if code > 0:
30
- return (False, f"Command failed with exit code {code}: {result['stderr']}")
31
- case _:
32
- pass
33
- return (False, "Unknown command result pattern")
34
-
35
-
36
- class HookStatus(Enum):
37
- SUCCESS = auto()
38
- FAILURE = auto()
39
- SKIPPED = auto()
40
- ERROR = auto()
41
-
42
-
43
- class HookResult(TypedDict):
44
- status: HookStatus
45
- hook_id: str
46
- output: str
47
- files: list[str]
48
-
49
-
50
- def analyze_hook_result(result: HookResult) -> str:
51
- match result:
52
- case {"status": HookStatus.SUCCESS, "hook_id": hook_id}:
53
- return f"✅ Hook {hook_id} passed successfully"
54
- case {"status": HookStatus.FAILURE, "hook_id": hook_id, "output": output} if (
55
- "fixable" in output
56
- ):
57
- return f"🔧 Hook {hook_id} failed with fixable issues"
58
- case {"status": HookStatus.FAILURE, "hook_id": hook_id}:
59
- return f"❌ Hook {hook_id} failed"
60
- case {"status": HookStatus.SKIPPED, "hook_id": hook_id}:
61
- return f"⏩ Hook {hook_id} was skipped"
62
- case {"status": HookStatus.ERROR, "hook_id": hook_id, "output": output}:
63
- return f"💥 Hook {hook_id} encountered an error: {output}"
64
- case _:
65
- pass
66
- return "Unknown hook result pattern"
67
-
68
-
69
- class ModernConfigManager:
70
- def __init__(self, config_path: Path) -> None:
71
- self.config_path = config_path
72
- self.config: dict[str, Any] = {}
73
-
74
- def load(self) -> Self:
75
- return self
76
-
77
- def update(self, key: str, value: Any) -> Self:
78
- self.config[key] = value
79
- return self
80
-
81
- def save(self) -> Self:
82
- return self
83
-
84
-
85
- def categorize_file(file_path: Path) -> str:
86
- path_str = str(file_path)
87
- name = file_path
88
- match path_str:
89
- case s if name.suffix == ".py" and "/ tests /" in s:
90
- return "Python Test File"
91
- case s if name.suffix == ".py" and "__init__.py" in name.name:
92
- return "Python Module Init"
93
- case s if name.suffix == ".py":
94
- return "Python Source File"
95
- case s if name.suffix in {".md", ".rst", ".txt"}:
96
- return "Documentation File"
97
- case s if name.stem.startswith(".") or name.name in {
98
- ".gitignore",
99
- ".pre-commit-config.yaml",
100
- }:
101
- return "Configuration File"
102
- case _:
103
- pass
104
- return "Unknown File Type"
105
-
106
-
107
- def process_hook_results[T, R](
108
- results: list[T],
109
- success_handler: typing.Callable[[T], R],
110
- failure_handler: typing.Callable[[T], R],
111
- ) -> list[R]:
112
- processed_results: list[R] = []
113
- for result in results:
114
- if (
115
- isinstance(result, dict)
116
- and "status" in result
117
- and result["status"] == HookStatus.SUCCESS
118
- ):
119
- processed_results.append(success_handler(result))
120
- else:
121
- processed_results.append(failure_handler(result))
122
- return processed_results
123
-
124
-
125
- class EnhancedCommandRunner:
126
- def __init__(self, working_dir: Path | None = None) -> None:
127
- self.working_dir = working_dir
128
-
129
- def run(self, cmd: list[str], **kwargs: Any) -> CommandResult:
130
- import time
131
-
132
- start_time = time.time()
133
- try:
134
- process = subprocess.run(
135
- cmd,
136
- check=False,
137
- capture_output=True,
138
- text=True,
139
- cwd=self.working_dir,
140
- **kwargs,
141
- )
142
- duration_ms = (time.time() - start_time) * 1000
143
- return CommandResult(
144
- success=process.returncode == 0,
145
- exit_code=process.returncode,
146
- stdout=process.stdout,
147
- stderr=process.stderr,
148
- command=cmd,
149
- duration_ms=duration_ms,
150
- )
151
- except subprocess.SubprocessError as e:
152
- duration_ms = (time.time() - start_time) * 1000
153
- return CommandResult(
154
- success=False,
155
- exit_code=-1,
156
- stdout="",
157
- stderr=str(e),
158
- command=cmd,
159
- duration_ms=duration_ms,
160
- )
161
-
162
- def handle_result(self, result: CommandResult) -> tuple[bool, str]:
163
- return process_command_output(result)
164
-
165
-
166
- def clean_python_code(code: str) -> str:
167
- lines = code.splitlines()
168
- cleaned_lines: list[str] = []
169
- for line in lines:
170
- processed_line = _process_line_for_cleaning(line, cleaned_lines)
171
- if processed_line is not None:
172
- cleaned_lines.append(processed_line)
173
- return "\n".join(cleaned_lines)
174
-
175
-
176
- def _process_line_for_cleaning(line: str, cleaned_lines: list[str]) -> str | None:
177
- """Process a single line for Python code cleaning.
178
-
179
- Returns:
180
- The processed line to add, or None if the line should be skipped.
181
- """
182
- stripped = line.strip()
183
-
184
- if _should_handle_empty_line(stripped, cleaned_lines):
185
- return ""
186
-
187
- if _is_import_line(stripped):
188
- return line
189
-
190
- if _is_comment_to_skip(stripped):
191
- return None
192
-
193
- if _has_inline_comment_to_process(stripped):
194
- return _extract_code_part(line)
195
-
196
- if _is_docstring_line(stripped):
197
- return None
198
-
199
- return line
200
-
201
-
202
- def _should_handle_empty_line(stripped: str, cleaned_lines: list[str]) -> bool:
203
- """Check if empty line should be preserved."""
204
- return stripped == "" and (not cleaned_lines or bool(cleaned_lines[-1].strip()))
205
-
206
-
207
- def _is_import_line(stripped: str) -> bool:
208
- """Check if line is an import statement."""
209
- return stripped.startswith(("import ", "from "))
210
-
211
-
212
- def _is_comment_to_skip(stripped: str) -> bool:
213
- """Check if line is a comment that should be skipped."""
214
- return stripped.startswith("#")
215
-
216
-
217
- def _has_inline_comment_to_process(stripped: str) -> bool:
218
- """Check if line has inline comment that should be processed."""
219
- if "#" not in stripped:
220
- return False
221
-
222
- skip_markers = ("# noqa", "# type: ", "# pragma", "# skip")
223
- return not any(skip in stripped for skip in skip_markers)
224
-
225
-
226
- def _extract_code_part(line: str) -> str | None:
227
- """Extract code part from line with inline comment."""
228
- code_part = line.split("#", 1)[0].rstrip()
229
- return code_part or None
230
-
231
-
232
- def _is_docstring_line(stripped: str) -> bool:
233
- """Check if line starts a docstring."""
234
- return stripped.startswith(('"""', "'''"))