crackerjack 0.31.10__py3-none-any.whl → 0.31.13__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (155) hide show
  1. crackerjack/CLAUDE.md +288 -705
  2. crackerjack/__main__.py +22 -8
  3. crackerjack/agents/__init__.py +0 -3
  4. crackerjack/agents/architect_agent.py +0 -43
  5. crackerjack/agents/base.py +1 -9
  6. crackerjack/agents/coordinator.py +2 -148
  7. crackerjack/agents/documentation_agent.py +109 -81
  8. crackerjack/agents/dry_agent.py +122 -97
  9. crackerjack/agents/formatting_agent.py +3 -16
  10. crackerjack/agents/import_optimization_agent.py +1174 -130
  11. crackerjack/agents/performance_agent.py +956 -188
  12. crackerjack/agents/performance_helpers.py +229 -0
  13. crackerjack/agents/proactive_agent.py +1 -48
  14. crackerjack/agents/refactoring_agent.py +516 -246
  15. crackerjack/agents/refactoring_helpers.py +282 -0
  16. crackerjack/agents/security_agent.py +393 -90
  17. crackerjack/agents/test_creation_agent.py +1776 -120
  18. crackerjack/agents/test_specialist_agent.py +59 -15
  19. crackerjack/agents/tracker.py +0 -102
  20. crackerjack/api.py +145 -37
  21. crackerjack/cli/handlers.py +48 -30
  22. crackerjack/cli/interactive.py +11 -11
  23. crackerjack/cli/options.py +66 -4
  24. crackerjack/code_cleaner.py +808 -148
  25. crackerjack/config/global_lock_config.py +110 -0
  26. crackerjack/config/hooks.py +43 -64
  27. crackerjack/core/async_workflow_orchestrator.py +247 -97
  28. crackerjack/core/autofix_coordinator.py +192 -109
  29. crackerjack/core/enhanced_container.py +46 -63
  30. crackerjack/core/file_lifecycle.py +549 -0
  31. crackerjack/core/performance.py +9 -8
  32. crackerjack/core/performance_monitor.py +395 -0
  33. crackerjack/core/phase_coordinator.py +281 -94
  34. crackerjack/core/proactive_workflow.py +9 -58
  35. crackerjack/core/resource_manager.py +501 -0
  36. crackerjack/core/service_watchdog.py +490 -0
  37. crackerjack/core/session_coordinator.py +4 -8
  38. crackerjack/core/timeout_manager.py +504 -0
  39. crackerjack/core/websocket_lifecycle.py +475 -0
  40. crackerjack/core/workflow_orchestrator.py +343 -209
  41. crackerjack/dynamic_config.py +50 -9
  42. crackerjack/errors.py +3 -4
  43. crackerjack/executors/async_hook_executor.py +63 -13
  44. crackerjack/executors/cached_hook_executor.py +14 -14
  45. crackerjack/executors/hook_executor.py +100 -37
  46. crackerjack/executors/hook_lock_manager.py +856 -0
  47. crackerjack/executors/individual_hook_executor.py +120 -86
  48. crackerjack/intelligence/__init__.py +0 -7
  49. crackerjack/intelligence/adaptive_learning.py +13 -86
  50. crackerjack/intelligence/agent_orchestrator.py +15 -78
  51. crackerjack/intelligence/agent_registry.py +12 -59
  52. crackerjack/intelligence/agent_selector.py +31 -92
  53. crackerjack/intelligence/integration.py +1 -41
  54. crackerjack/interactive.py +9 -9
  55. crackerjack/managers/async_hook_manager.py +25 -8
  56. crackerjack/managers/hook_manager.py +9 -9
  57. crackerjack/managers/publish_manager.py +57 -59
  58. crackerjack/managers/test_command_builder.py +6 -36
  59. crackerjack/managers/test_executor.py +9 -61
  60. crackerjack/managers/test_manager.py +17 -63
  61. crackerjack/managers/test_manager_backup.py +77 -127
  62. crackerjack/managers/test_progress.py +4 -23
  63. crackerjack/mcp/cache.py +5 -12
  64. crackerjack/mcp/client_runner.py +10 -10
  65. crackerjack/mcp/context.py +64 -6
  66. crackerjack/mcp/dashboard.py +14 -11
  67. crackerjack/mcp/enhanced_progress_monitor.py +55 -55
  68. crackerjack/mcp/file_monitor.py +72 -42
  69. crackerjack/mcp/progress_components.py +103 -84
  70. crackerjack/mcp/progress_monitor.py +122 -49
  71. crackerjack/mcp/rate_limiter.py +12 -12
  72. crackerjack/mcp/server_core.py +16 -22
  73. crackerjack/mcp/service_watchdog.py +26 -26
  74. crackerjack/mcp/state.py +15 -0
  75. crackerjack/mcp/tools/core_tools.py +95 -39
  76. crackerjack/mcp/tools/error_analyzer.py +6 -32
  77. crackerjack/mcp/tools/execution_tools.py +1 -56
  78. crackerjack/mcp/tools/execution_tools_backup.py +35 -131
  79. crackerjack/mcp/tools/intelligence_tool_registry.py +0 -36
  80. crackerjack/mcp/tools/intelligence_tools.py +2 -55
  81. crackerjack/mcp/tools/monitoring_tools.py +308 -145
  82. crackerjack/mcp/tools/proactive_tools.py +12 -42
  83. crackerjack/mcp/tools/progress_tools.py +23 -15
  84. crackerjack/mcp/tools/utility_tools.py +3 -40
  85. crackerjack/mcp/tools/workflow_executor.py +40 -60
  86. crackerjack/mcp/websocket/app.py +0 -3
  87. crackerjack/mcp/websocket/endpoints.py +206 -268
  88. crackerjack/mcp/websocket/jobs.py +213 -66
  89. crackerjack/mcp/websocket/server.py +84 -6
  90. crackerjack/mcp/websocket/websocket_handler.py +137 -29
  91. crackerjack/models/config_adapter.py +3 -16
  92. crackerjack/models/protocols.py +162 -3
  93. crackerjack/models/resource_protocols.py +454 -0
  94. crackerjack/models/task.py +3 -3
  95. crackerjack/monitoring/__init__.py +0 -0
  96. crackerjack/monitoring/ai_agent_watchdog.py +25 -71
  97. crackerjack/monitoring/regression_prevention.py +28 -87
  98. crackerjack/orchestration/advanced_orchestrator.py +44 -78
  99. crackerjack/orchestration/coverage_improvement.py +10 -60
  100. crackerjack/orchestration/execution_strategies.py +16 -16
  101. crackerjack/orchestration/test_progress_streamer.py +61 -53
  102. crackerjack/plugins/base.py +1 -1
  103. crackerjack/plugins/managers.py +22 -20
  104. crackerjack/py313.py +65 -21
  105. crackerjack/services/backup_service.py +467 -0
  106. crackerjack/services/bounded_status_operations.py +627 -0
  107. crackerjack/services/cache.py +7 -9
  108. crackerjack/services/config.py +35 -52
  109. crackerjack/services/config_integrity.py +5 -16
  110. crackerjack/services/config_merge.py +542 -0
  111. crackerjack/services/contextual_ai_assistant.py +17 -19
  112. crackerjack/services/coverage_ratchet.py +44 -73
  113. crackerjack/services/debug.py +25 -39
  114. crackerjack/services/dependency_monitor.py +52 -50
  115. crackerjack/services/enhanced_filesystem.py +14 -11
  116. crackerjack/services/file_hasher.py +1 -1
  117. crackerjack/services/filesystem.py +1 -12
  118. crackerjack/services/git.py +71 -47
  119. crackerjack/services/health_metrics.py +31 -27
  120. crackerjack/services/initialization.py +276 -428
  121. crackerjack/services/input_validator.py +760 -0
  122. crackerjack/services/log_manager.py +16 -16
  123. crackerjack/services/logging.py +7 -6
  124. crackerjack/services/metrics.py +43 -43
  125. crackerjack/services/pattern_cache.py +2 -31
  126. crackerjack/services/pattern_detector.py +26 -63
  127. crackerjack/services/performance_benchmarks.py +20 -45
  128. crackerjack/services/regex_patterns.py +2887 -0
  129. crackerjack/services/regex_utils.py +537 -0
  130. crackerjack/services/secure_path_utils.py +683 -0
  131. crackerjack/services/secure_status_formatter.py +534 -0
  132. crackerjack/services/secure_subprocess.py +605 -0
  133. crackerjack/services/security.py +47 -10
  134. crackerjack/services/security_logger.py +492 -0
  135. crackerjack/services/server_manager.py +109 -50
  136. crackerjack/services/smart_scheduling.py +8 -25
  137. crackerjack/services/status_authentication.py +603 -0
  138. crackerjack/services/status_security_manager.py +442 -0
  139. crackerjack/services/thread_safe_status_collector.py +546 -0
  140. crackerjack/services/tool_version_service.py +1 -23
  141. crackerjack/services/unified_config.py +36 -58
  142. crackerjack/services/validation_rate_limiter.py +269 -0
  143. crackerjack/services/version_checker.py +9 -40
  144. crackerjack/services/websocket_resource_limiter.py +572 -0
  145. crackerjack/slash_commands/__init__.py +52 -2
  146. crackerjack/tools/__init__.py +0 -0
  147. crackerjack/tools/validate_input_validator_patterns.py +262 -0
  148. crackerjack/tools/validate_regex_patterns.py +198 -0
  149. {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/METADATA +197 -12
  150. crackerjack-0.31.13.dist-info/RECORD +178 -0
  151. crackerjack/cli/facade.py +0 -104
  152. crackerjack-0.31.10.dist-info/RECORD +0 -149
  153. {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/WHEEL +0 -0
  154. {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/entry_points.txt +0 -0
  155. {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/licenses/LICENSE +0 -0
@@ -15,18 +15,16 @@ class ConfigurationService:
15
15
  self.config_generator = DynamicConfigGenerator()
16
16
 
17
17
  def update_precommit_config(self, options: OptionsProtocol) -> bool:
18
- """Update pre-commit configuration and dynamic config versions."""
19
18
  try:
20
- # Generate config first
21
19
  mode = self._determine_config_mode(options)
22
20
  config_temp_path = generate_config_for_mode(mode)
23
21
  if not config_temp_path:
24
- self.console.print("[yellow]⚠️ No configuration generated[/yellow]")
22
+ self.console.print("[yellow]⚠️ No configuration generated[/ yellow]")
25
23
  return False
26
24
 
27
25
  config_file = self.pkg_path / ".pre-commit-config.yaml"
28
26
  config_content = config_temp_path.read_text()
29
- # Clean trailing whitespace and ensure single trailing newline
27
+
30
28
  from crackerjack.services.filesystem import FileSystemService
31
29
 
32
30
  config_content = FileSystemService.clean_trailing_whitespace_and_newlines(
@@ -35,25 +33,23 @@ class ConfigurationService:
35
33
  config_file.write_text(config_content)
36
34
 
37
35
  self._temp_config_path = config_temp_path
38
- self.console.print("[green]✅[/green] Pre-commit configuration generated")
36
+ self.console.print("[green]✅[/ green] Pre-commit configuration generated")
39
37
 
40
- # Run pre-commit autoupdate if requested via -u flag
41
38
  if getattr(options, "update_precommit", False):
42
39
  success = self._run_precommit_autoupdate()
43
40
  if success:
44
- self.console.print("[green]✅[/green] Pre-commit hooks updated")
41
+ self.console.print("[green]✅[/ green] Pre-commit hooks updated")
45
42
  else:
46
43
  self.console.print(
47
- "[yellow]⚠️[/yellow] Pre-commit autoupdate had issues"
44
+ "[yellow]⚠️[/ yellow] Pre-commit autoupdate had issues"
48
45
  )
49
46
 
50
- # Also update dynamic config versions
51
47
  self._update_dynamic_config_versions()
52
48
 
53
49
  return True
54
50
  except Exception as e:
55
51
  self.console.print(
56
- f"[red]❌[/red] Failed to generate pre-commit config: {e}",
52
+ f"[red]❌[/ red] Failed to generate pre-commit config: {e}",
57
53
  )
58
54
  return False
59
55
 
@@ -72,7 +68,7 @@ class ConfigurationService:
72
68
  config_file = self.pkg_path / ".pre-commit-config.yaml"
73
69
  if not config_file.exists():
74
70
  self.console.print(
75
- "[yellow]⚠️ No pre-commit configuration found[/yellow]",
71
+ "[yellow]⚠️ No pre-commit configuration found[/ yellow]",
76
72
  )
77
73
  return False
78
74
  import yaml
@@ -84,10 +80,10 @@ class ConfigurationService:
84
80
  if yaml_result is not None
85
81
  else {}
86
82
  )
87
- self.console.print("[green]✅[/green] Pre-commit configuration is valid")
83
+ self.console.print("[green]✅[/ green] Pre-commit configuration is valid")
88
84
  return True
89
85
  except Exception as e:
90
- self.console.print(f"[red]❌[/red] Configuration validation failed: {e}")
86
+ self.console.print(f"[red]❌[/ red] Configuration validation failed: {e}")
91
87
  return False
92
88
 
93
89
  def backup_config(self) -> Path | None:
@@ -101,12 +97,12 @@ class ConfigurationService:
101
97
  backup_file = self.pkg_path / f".pre-commit-config.yaml.backup.{timestamp}"
102
98
  backup_file.write_text(config_file.read_text())
103
99
  self.console.print(
104
- f"[cyan]💾[/cyan] Configuration backed up to {backup_file.name}",
100
+ f"[cyan]💾[/ cyan] Configuration backed up to {backup_file.name}",
105
101
  )
106
102
  return backup_file
107
103
  except Exception as e:
108
104
  self.console.print(
109
- f"[yellow]⚠️[/yellow] Failed to backup configuration: {e}",
105
+ f"[yellow]⚠️[/ yellow] Failed to backup configuration: {e}",
110
106
  )
111
107
  return None
112
108
 
@@ -114,17 +110,17 @@ class ConfigurationService:
114
110
  try:
115
111
  if not backup_file.exists():
116
112
  self.console.print(
117
- f"[red]❌[/red] Backup file not found: {backup_file}",
113
+ f"[red]❌[/ red] Backup file not found: {backup_file}",
118
114
  )
119
115
  return False
120
116
  config_file = self.pkg_path / ".pre-commit-config.yaml"
121
117
  config_file.write_text(backup_file.read_text())
122
118
  self.console.print(
123
- f"[green]✅[/green] Configuration restored from {backup_file.name}",
119
+ f"[green]✅[/ green] Configuration restored from {backup_file.name}",
124
120
  )
125
121
  return True
126
122
  except Exception as e:
127
- self.console.print(f"[red]❌[/red] Failed to restore configuration: {e}")
123
+ self.console.print(f"[red]❌[/ red] Failed to restore configuration: {e}")
128
124
  return False
129
125
 
130
126
  def get_config_info(self) -> dict[str, t.Any]:
@@ -172,7 +168,7 @@ class ConfigurationService:
172
168
  try:
173
169
  pyproject_file = self.pkg_path / "pyproject.toml"
174
170
  if not pyproject_file.exists():
175
- self.console.print("[yellow]⚠️ No pyproject.toml found[/yellow]")
171
+ self.console.print("[yellow]⚠️ No pyproject.toml found[/ yellow]")
176
172
  return False
177
173
  from tomllib import loads
178
174
 
@@ -192,7 +188,7 @@ class ConfigurationService:
192
188
  "show-fixes": True,
193
189
  "output-format": "full",
194
190
  }
195
- config["tool"]["ruff"]["format"] = {"docstring-code-format": True}
191
+ config["tool"]["ruff"]["format"] = {"docstring - code-format": True}
196
192
  config["tool"]["ruff"]["lint"] = {
197
193
  "extend-select": ["C901", "F", "I", "UP"],
198
194
  "ignore": ["E402", "F821"],
@@ -203,7 +199,7 @@ class ConfigurationService:
203
199
  "ini_options": {
204
200
  "asyncio_mode": "auto",
205
201
  "timeout": 300,
206
- "addopts": "--cov=crackerjack --cov-report=term",
202
+ "addopts": "- - cov=crackerjack - - cov-report=term",
207
203
  "markers": [
208
204
  "unit: marks test as a unit test",
209
205
  "benchmark: mark test as a benchmark",
@@ -212,25 +208,26 @@ class ConfigurationService:
212
208
  ],
213
209
  },
214
210
  }
215
- # Clean the content before writing to prevent hook failures
211
+
216
212
  from crackerjack.services.filesystem import FileSystemService
217
213
 
218
214
  content = dumps(config)
219
215
  content = FileSystemService.clean_trailing_whitespace_and_newlines(content)
220
216
  with pyproject_file.open("w") as f:
221
217
  f.write(content)
222
- self.console.print("[green]✅[/green] pyproject.toml configuration updated")
218
+ self.console.print(
219
+ "[green]✅[/ green] pyproject.toml configuration updated"
220
+ )
223
221
  return True
224
222
  except Exception as e:
225
- self.console.print(f"[red]❌[/red] Failed to update pyproject.toml: {e}")
223
+ self.console.print(f"[red]❌[/ red] Failed to update pyproject.toml: {e}")
226
224
  return False
227
225
 
228
226
  def _run_precommit_autoupdate(self) -> bool:
229
- """Run pre-commit autoupdate to get latest hook versions."""
230
227
  import subprocess
231
228
 
232
229
  try:
233
- self.console.print("[cyan]🔄[/cyan] Running pre-commit autoupdate...")
230
+ self.console.print("[cyan]🔄[/ cyan] Running pre-commit autoupdate...")
234
231
  result = self._execute_precommit_autoupdate()
235
232
 
236
233
  if result.returncode == 0:
@@ -241,17 +238,15 @@ class ConfigurationService:
241
238
  return False
242
239
 
243
240
  except subprocess.TimeoutExpired:
244
- self.console.print("[red]❌[/red] Pre-commit autoupdate timed out")
241
+ self.console.print("[red]❌[/ red] Pre-commit autoupdate timed out")
245
242
  return False
246
243
  except Exception as e:
247
244
  self.console.print(
248
- f"[red]❌[/red] Failed to run pre-commit autoupdate: {e}"
245
+ f"[red]❌[/ red] Failed to run pre-commit autoupdate: {e}"
249
246
  )
250
247
  return False
251
248
 
252
249
  def _execute_precommit_autoupdate(self) -> subprocess.CompletedProcess[str]:
253
- """Execute the pre-commit autoupdate command."""
254
-
255
250
  return subprocess.run(
256
251
  ["uv", "run", "pre-commit", "autoupdate"],
257
252
  cwd=self.pkg_path,
@@ -261,32 +256,27 @@ class ConfigurationService:
261
256
  )
262
257
 
263
258
  def _display_autoupdate_results(self, stdout: str) -> None:
264
- """Display updated versions if any."""
265
259
  if self._has_updates(stdout):
266
260
  for line in stdout.split("\n"):
267
261
  if self._is_update_line(line):
268
- self.console.print(f"[dim] {line.strip()}[/dim]")
262
+ self.console.print(f"[dim] {line.strip()}[/ dim]")
269
263
 
270
264
  def _has_updates(self, stdout: str) -> bool:
271
- """Check if the output contains update information."""
272
265
  stdout_lower = stdout.lower()
273
266
  return "updating" in stdout_lower or "updated" in stdout_lower
274
267
 
275
268
  def _is_update_line(self, line: str) -> bool:
276
- """Check if a line contains update information."""
277
- return "updating" in line.lower() or "->" in line
269
+ return "updating" in line.lower() or "- >" in line
278
270
 
279
271
  def _handle_autoupdate_error(self, stderr: str) -> None:
280
- """Handle pre-commit autoupdate error output."""
281
272
  if stderr:
282
273
  self.console.print(
283
- f"[yellow]Pre-commit autoupdate stderr:[/yellow] {stderr}"
274
+ f"[yellow]Pre-commit autoupdate stderr: [/ yellow] {stderr}"
284
275
  )
285
276
 
286
277
  def _update_dynamic_config_versions(self) -> None:
287
- """Update hardcoded versions in dynamic_config.py based on .pre-commit-config.yaml."""
288
278
  try:
289
- self.console.print("[cyan]🔄[/cyan] Updating dynamic config versions...")
279
+ self.console.print("[cyan]🔄[/ cyan] Updating dynamic config versions...")
290
280
 
291
281
  version_updates = self._extract_version_updates()
292
282
  if version_updates:
@@ -294,11 +284,10 @@ class ConfigurationService:
294
284
 
295
285
  except Exception as e:
296
286
  self.console.print(
297
- f"[yellow]⚠️[/yellow] Failed to update dynamic config versions: {e}"
287
+ f"[yellow]⚠️[/ yellow] Failed to update dynamic config versions: {e}"
298
288
  )
299
289
 
300
290
  def _extract_version_updates(self) -> dict[str, str]:
301
- """Extract version mappings from .pre-commit-config.yaml."""
302
291
  config_file = self.pkg_path / ".pre-commit-config.yaml"
303
292
  if not config_file.exists():
304
293
  return {}
@@ -322,7 +311,6 @@ class ConfigurationService:
322
311
  return version_updates
323
312
 
324
313
  def _update_dynamic_config_file(self, version_updates: dict[str, str]) -> None:
325
- """Update dynamic_config.py with version mappings."""
326
314
  dynamic_config_path = self.pkg_path / "crackerjack" / "dynamic_config.py"
327
315
  if dynamic_config_path.exists():
328
316
  self._apply_version_updates(dynamic_config_path, version_updates)
@@ -330,29 +318,24 @@ class ConfigurationService:
330
318
  def _apply_version_updates(
331
319
  self, config_path: Path, version_updates: dict[str, str]
332
320
  ) -> None:
333
- """Apply version updates to dynamic_config.py."""
334
321
  try:
335
322
  content = config_path.read_text()
336
323
  updated = False
337
324
 
338
325
  for repo_url, new_rev in version_updates.items():
339
- # Find and update the revision for this repo
340
- import re
341
-
342
- pattern = rf'("repo": "{re.escape(repo_url)}".*?"rev": )"([^"]+)"'
343
- replacement = rf'\1"{new_rev}"'
326
+ from .regex_patterns import update_repo_revision
344
327
 
345
- new_content = re.sub(pattern, replacement, content, flags=re.DOTALL)
328
+ new_content = update_repo_revision(content, repo_url, new_rev)
346
329
  if new_content != content:
347
330
  content = new_content
348
331
  updated = True
349
- self.console.print(f"[dim] Updated {repo_url} to {new_rev}[/dim]")
332
+ self.console.print(f"[dim] Updated {repo_url} to {new_rev}[/ dim]")
350
333
 
351
334
  if updated:
352
335
  config_path.write_text(content)
353
- self.console.print("[green]✅[/green] Dynamic config versions updated")
336
+ self.console.print("[green]✅[/ green] Dynamic config versions updated")
354
337
 
355
338
  except Exception as e:
356
339
  self.console.print(
357
- f"[yellow]⚠️[/yellow] Failed to apply version updates: {e}"
340
+ f"[yellow]⚠️[/ yellow] Failed to apply version updates: {e}"
358
341
  )
@@ -1,17 +1,9 @@
1
- """Configuration integrity checking service.
2
-
3
- This module handles detection of configuration file changes and validates
4
- required configuration sections. Split from tool_version_service.py.
5
- """
6
-
7
1
  from pathlib import Path
8
2
 
9
3
  from rich.console import Console
10
4
 
11
5
 
12
6
  class ConfigIntegrityService:
13
- """Service for checking configuration file integrity and required sections."""
14
-
15
7
  def __init__(self, console: Console, project_path: Path) -> None:
16
8
  self.console = console
17
9
  self.project_path = project_path
@@ -19,7 +11,6 @@ class ConfigIntegrityService:
19
11
  self.cache_dir.mkdir(parents=True, exist_ok=True)
20
12
 
21
13
  def check_config_integrity(self) -> bool:
22
- """Check for configuration file drift and missing required sections."""
23
14
  config_files = [
24
15
  ".pre-commit-config.yaml",
25
16
  "pyproject.toml",
@@ -34,14 +25,13 @@ class ConfigIntegrityService:
34
25
 
35
26
  if not self._has_required_config_sections():
36
27
  self.console.print(
37
- "[yellow]⚠️ Configuration missing required sections[/yellow]",
28
+ "[yellow]⚠️ Configuration missing required sections[/ yellow]",
38
29
  )
39
30
  drift_detected = True
40
31
 
41
32
  return drift_detected
42
33
 
43
34
  def _check_file_drift(self, file_path: Path) -> bool:
44
- """Check if a configuration file has been modified since last check."""
45
35
  cache_file = self.cache_dir / f"{file_path.name}.hash"
46
36
 
47
37
  try:
@@ -55,7 +45,7 @@ class ConfigIntegrityService:
55
45
  cached_hash = int(cache_file.read_text().strip())
56
46
  if current_hash != cached_hash:
57
47
  self.console.print(
58
- f"[yellow]⚠️ {file_path.name} has been modified manually[/yellow]",
48
+ f"[yellow]⚠️ {file_path.name} has been modified manually[/ yellow]",
59
49
  )
60
50
  return True
61
51
 
@@ -63,11 +53,10 @@ class ConfigIntegrityService:
63
53
  return False
64
54
 
65
55
  except OSError as e:
66
- self.console.print(f"[red]❌ Error checking {file_path.name}: {e}[/red]")
56
+ self.console.print(f"[red]❌ Error checking {file_path.name}: {e}[/ red]")
67
57
  return False
68
58
 
69
59
  def _has_required_config_sections(self) -> bool:
70
- """Check if pyproject.toml has all required configuration sections."""
71
60
  pyproject = self.project_path / "pyproject.toml"
72
61
  if not pyproject.exists():
73
62
  return False
@@ -87,7 +76,7 @@ class ConfigIntegrityService:
87
76
  for key in keys:
88
77
  if key not in current:
89
78
  self.console.print(
90
- f"[yellow]⚠️ Missing required config section: {section}[/yellow]",
79
+ f"[yellow]⚠️ Missing required config section: {section}[/ yellow]",
91
80
  )
92
81
  return False
93
82
  current = current[key]
@@ -95,5 +84,5 @@ class ConfigIntegrityService:
95
84
  return True
96
85
 
97
86
  except Exception as e:
98
- self.console.print(f"[red]❌ Error parsing pyproject.toml: {e}[/red]")
87
+ self.console.print(f"[red]❌ Error parsing pyproject.toml: {e}[/ red]")
99
88
  return False