crackerjack 0.38.10__py3-none-any.whl → 0.38.11__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.

crackerjack/__main__.py CHANGED
@@ -1543,6 +1543,47 @@ def _handle_specialized_analytics(local_vars: t.Any, console: t.Any) -> bool:
1543
1543
  return _handle_enterprise_features(local_vars, console)
1544
1544
 
1545
1545
 
1546
+ def _display_coverage_info(console: t.Any, coverage_info: dict[str, t.Any]) -> None:
1547
+ """Display basic coverage information."""
1548
+ coverage_percent = coverage_info.get("coverage_percent", 0.0)
1549
+ coverage_source = coverage_info.get("source", "unknown")
1550
+
1551
+ if coverage_percent > 0:
1552
+ console.print(
1553
+ f"[green]Current Coverage:[/green] {coverage_percent:.2f}% (from {coverage_source})"
1554
+ )
1555
+ else:
1556
+ console.print("[yellow]Current Coverage:[/yellow] No coverage data available")
1557
+
1558
+ # Show status message if available
1559
+ status_message = coverage_info.get("message")
1560
+ if status_message:
1561
+ console.print(f"[dim]{status_message}[/dim]")
1562
+
1563
+
1564
+ def _display_coverage_report(console: t.Any, test_manager: t.Any) -> None:
1565
+ """Display detailed coverage report if available."""
1566
+ coverage_report = test_manager.get_coverage_report()
1567
+ if coverage_report:
1568
+ console.print(f"[cyan]Details:[/cyan] {coverage_report}")
1569
+
1570
+
1571
+ def _display_ratchet_status(console: t.Any, test_manager: t.Any) -> None:
1572
+ """Display coverage ratchet status if available."""
1573
+ from contextlib import suppress
1574
+
1575
+ with suppress(Exception):
1576
+ ratchet_status = test_manager.get_coverage_ratchet_status()
1577
+ if ratchet_status:
1578
+ next_milestone = ratchet_status.get("next_milestone")
1579
+ if next_milestone:
1580
+ console.print(f"[cyan]Next Milestone:[/cyan] {next_milestone:.0f}%")
1581
+
1582
+ milestones = ratchet_status.get("milestones_achieved", [])
1583
+ if milestones:
1584
+ console.print(f"[green]Milestones Achieved:[/green] {len(milestones)}")
1585
+
1586
+
1546
1587
  def _handle_coverage_status(
1547
1588
  coverage_status: bool, console: t.Any, options: t.Any
1548
1589
  ) -> bool:
@@ -1566,43 +1607,13 @@ def _handle_coverage_status(
1566
1607
 
1567
1608
  # Get coverage information
1568
1609
  coverage_info = test_manager.get_coverage()
1569
- coverage_percent = coverage_info.get("coverage_percent", 0.0)
1570
- coverage_source = coverage_info.get("source", "unknown")
1571
-
1572
- if coverage_percent > 0:
1573
- console.print(
1574
- f"[green]Current Coverage:[/green] {coverage_percent:.2f}% (from {coverage_source})"
1575
- )
1576
- else:
1577
- console.print(
1578
- "[yellow]Current Coverage:[/yellow] No coverage data available"
1579
- )
1580
-
1581
- # Show status message if available
1582
- status_message = coverage_info.get("message")
1583
- if status_message:
1584
- console.print(f"[dim]{status_message}[/dim]")
1610
+ _display_coverage_info(console, coverage_info)
1585
1611
 
1586
1612
  # Try to get more detailed coverage report
1587
- coverage_report = test_manager.get_coverage_report()
1588
- if coverage_report:
1589
- console.print(f"[cyan]Details:[/cyan] {coverage_report}")
1613
+ _display_coverage_report(console, test_manager)
1590
1614
 
1591
1615
  # Show coverage ratchet status if available
1592
- try:
1593
- ratchet_status = test_manager.get_coverage_ratchet_status()
1594
- if ratchet_status:
1595
- next_milestone = ratchet_status.get("next_milestone")
1596
- if next_milestone:
1597
- console.print(f"[cyan]Next Milestone:[/cyan] {next_milestone:.0f}%")
1598
-
1599
- milestones = ratchet_status.get("milestones_achieved", [])
1600
- if milestones:
1601
- console.print(
1602
- f"[green]Milestones Achieved:[/green] {len(milestones)}"
1603
- )
1604
- except Exception:
1605
- pass # Ignore ratchet status errors
1616
+ _display_ratchet_status(console, test_manager)
1606
1617
 
1607
1618
  console.print()
1608
1619
  return False # Exit after showing status
@@ -34,6 +34,26 @@ class InteractiveWorkflowOptions:
34
34
  interactive: bool = True
35
35
  dry_run: bool = False
36
36
 
37
+ def __init__(
38
+ self,
39
+ clean: bool = False,
40
+ test: bool = False,
41
+ publish: str | None = None,
42
+ bump: str | None = None,
43
+ commit: bool = False,
44
+ create_pr: bool = False,
45
+ interactive: bool = True,
46
+ dry_run: bool = False,
47
+ ) -> None:
48
+ self.clean = clean
49
+ self.test = test
50
+ self.publish = publish
51
+ self.bump = bump
52
+ self.commit = commit
53
+ self.create_pr = create_pr
54
+ self.interactive = interactive
55
+ self.dry_run = dry_run
56
+
37
57
  @classmethod
38
58
  def from_args(cls, args: t.Any) -> "InteractiveWorkflowOptions":
39
59
  return cls(
@@ -38,23 +38,25 @@ class TestCommandBuilder:
38
38
  # Method 1: Try to read from pyproject.toml
39
39
  pyproject_path = self.pkg_path / "pyproject.toml"
40
40
  if pyproject_path.exists():
41
- try:
41
+ from contextlib import suppress
42
+
43
+ with suppress(Exception):
42
44
  import tomllib
45
+
43
46
  with pyproject_path.open("rb") as f:
44
47
  data = tomllib.load(f)
45
48
  project_name = data.get("project", {}).get("name")
46
49
  if project_name:
47
50
  # Convert project name to package name (hyphens to underscores)
48
51
  return project_name.replace("-", "_")
49
- except Exception:
50
- pass # Fall back to directory detection
52
+ # Fall back to directory detection
51
53
 
52
54
  # Method 2: Look for Python packages in the project root
53
55
  for item in self.pkg_path.iterdir():
54
56
  if (
55
57
  item.is_dir()
56
58
  and not item.name.startswith(".")
57
- and not item.name in ("tests", "docs", "build", "dist", "__pycache__")
59
+ and item.name not in ("tests", "docs", "build", "dist", "__pycache__")
58
60
  and (item / "__init__.py").exists()
59
61
  ):
60
62
  return item.name
@@ -128,66 +128,91 @@ class TestManager:
128
128
  except Exception:
129
129
  return None
130
130
 
131
+ def _get_coverage_from_file(self) -> float | None:
132
+ """Extract coverage from coverage.json file."""
133
+ import json
134
+
135
+ coverage_json_path = self.pkg_path / "coverage.json"
136
+ if not coverage_json_path.exists():
137
+ return None
138
+
139
+ try:
140
+ with coverage_json_path.open() as f:
141
+ coverage_data = json.load(f)
142
+
143
+ # Extract coverage percentage from totals
144
+ totals = coverage_data.get("totals", {})
145
+ percent_covered = totals.get("percent_covered", None)
146
+
147
+ if percent_covered is not None:
148
+ return float(percent_covered)
149
+
150
+ # Alternative extraction methods for different coverage formats
151
+ if "percent_covered" in coverage_data:
152
+ return float(coverage_data["percent_covered"])
153
+
154
+ # Check for coverage in files section
155
+ files = coverage_data.get("files", {})
156
+ if files:
157
+ total_lines = 0
158
+ covered_lines = 0
159
+ for file_data in files.values():
160
+ summary = file_data.get("summary", {})
161
+ total_lines += summary.get("num_statements", 0)
162
+ covered_lines += summary.get("covered_lines", 0)
163
+
164
+ if total_lines > 0:
165
+ return (covered_lines / total_lines) * 100
166
+
167
+ return None
168
+
169
+ except (json.JSONDecodeError, ValueError, KeyError, TypeError):
170
+ return None
171
+
172
+ def _handle_no_ratchet_status(
173
+ self, direct_coverage: float | None
174
+ ) -> dict[str, t.Any]:
175
+ """Handle case when ratchet is not initialized."""
176
+ if direct_coverage is not None:
177
+ return {
178
+ "status": "coverage_available",
179
+ "coverage_percent": direct_coverage,
180
+ "message": "Coverage data available from coverage.json",
181
+ "source": "coverage.json",
182
+ }
183
+
184
+ return {
185
+ "status": "not_initialized",
186
+ "coverage_percent": 0.0,
187
+ "message": "Coverage ratchet not initialized",
188
+ }
189
+
190
+ def _get_final_coverage(
191
+ self, ratchet_coverage: float, direct_coverage: float | None
192
+ ) -> float:
193
+ """Determine final coverage value."""
194
+ return direct_coverage if direct_coverage is not None else ratchet_coverage
195
+
131
196
  def get_coverage(self) -> dict[str, t.Any]:
132
197
  try:
133
198
  status = self.coverage_ratchet.get_status_report()
134
199
 
135
200
  # Check if we have actual coverage data from coverage.json even if ratchet is not initialized
136
- coverage_json_path = self.pkg_path / "coverage.json"
137
- direct_coverage = None
138
-
139
- if coverage_json_path.exists():
140
- try:
141
- import json
142
-
143
- with coverage_json_path.open() as f:
144
- data = json.load(f)
145
- # Check for totals field first (newer format)
146
- direct_coverage = data.get("totals", {}).get("percent_covered")
147
-
148
- # If no totals, calculate from files data (standard pytest-cov format)
149
- if direct_coverage is None and "files" in data:
150
- total_statements = 0
151
- total_covered = 0
152
-
153
- for file_data in data["files"].values():
154
- summary = file_data.get("summary", {})
155
- statements = summary.get("num_statements", 0)
156
- covered = summary.get("covered_lines", 0)
157
- total_statements += statements
158
- total_covered += covered
159
-
160
- if total_statements > 0:
161
- direct_coverage = (
162
- total_covered / total_statements
163
- ) * 100
164
- except (json.JSONDecodeError, KeyError):
165
- pass # Fall back to ratchet data
201
+ direct_coverage = self._get_coverage_from_file()
166
202
 
167
203
  # If ratchet is not initialized but we have direct coverage data, use it
168
204
  if (
169
205
  not status or status.get("status") == "not_initialized"
170
206
  ) and direct_coverage is not None:
171
- return {
172
- "status": "coverage_available",
173
- "coverage_percent": direct_coverage,
174
- "message": "Coverage data available from coverage.json",
175
- "source": "coverage.json",
176
- }
207
+ return self._handle_no_ratchet_status(direct_coverage)
177
208
 
178
209
  # If ratchet is not initialized and no direct coverage, return not initialized
179
210
  if not status or status.get("status") == "not_initialized":
180
- return {
181
- "status": "not_initialized",
182
- "coverage_percent": 0.0,
183
- "message": "Coverage ratchet not initialized",
184
- }
211
+ return self._handle_no_ratchet_status(None)
185
212
 
186
213
  # Use ratchet data, but prefer direct coverage if available and different
187
214
  ratchet_coverage = status.get("current_coverage", 0.0)
188
- final_coverage = (
189
- direct_coverage if direct_coverage is not None else ratchet_coverage
190
- )
215
+ final_coverage = self._get_final_coverage(ratchet_coverage, direct_coverage)
191
216
 
192
217
  return {
193
218
  "status": "active",
@@ -277,74 +302,65 @@ class TestManager:
277
302
 
278
303
  return self._handle_ratchet_result(ratchet_result)
279
304
 
280
- def _update_coverage_badge(self, ratchet_result: dict[str, t.Any]) -> None:
281
- """Update coverage badge in README.md if coverage changed."""
282
- try:
283
- # Get current coverage directly from coverage.json to ensure freshest data
284
- import json
285
-
286
- current_coverage = None
287
- coverage_json_path = self.pkg_path / "coverage.json"
288
-
289
- # Primary: Try to extract from coverage.json
290
- if coverage_json_path.exists():
291
- try:
292
- with coverage_json_path.open() as f:
293
- data = json.load(f)
294
- # Check for totals field first (newer format)
295
- current_coverage = data.get("totals", {}).get("percent_covered")
296
-
297
- # If no totals, calculate from files data (standard pytest-cov format)
298
- if current_coverage is None and "files" in data:
299
- total_statements = 0
300
- total_covered = 0
301
-
302
- for file_data in data["files"].values():
303
- summary = file_data.get("summary", {})
304
- statements = summary.get("num_statements", 0)
305
- covered = summary.get("covered_lines", 0)
306
- total_statements += statements
307
- total_covered += covered
308
-
309
- if total_statements > 0:
310
- current_coverage = (
311
- total_covered / total_statements
312
- ) * 100
313
-
314
- if current_coverage is not None:
315
- self.console.print(
316
- f"[dim]📊 Coverage extracted from coverage.json: {current_coverage:.2f}%[/dim]"
317
- )
318
- except (json.JSONDecodeError, KeyError) as e:
319
- self.console.print(
320
- f"[yellow]⚠️[/yellow] Failed to parse coverage.json: {e}"
321
- )
305
+ def _attempt_coverage_extraction(self) -> float | None:
306
+ """Attempt to extract coverage from various sources."""
307
+ # Primary: Try to extract from coverage.json
308
+ current_coverage = self._get_coverage_from_file()
309
+ if current_coverage is not None:
310
+ return current_coverage
322
311
 
323
- # Secondary: Try ratchet result if coverage.json failed
324
- if current_coverage is None:
325
- current_coverage = ratchet_result.get("current_coverage")
326
- if current_coverage is not None:
327
- self.console.print(
328
- f"[dim]📊 Coverage from ratchet result: {current_coverage:.2f}%[/dim]"
329
- )
312
+ return None
330
313
 
331
- # Tertiary: Try coverage service, but only accept non-zero values
332
- if current_coverage is None:
333
- coverage_info = self.get_coverage()
334
- fallback_coverage = coverage_info.get("coverage_percent")
335
- # Only use fallback if it's meaningful (>0) or if no coverage.json exists
336
- if fallback_coverage and (
337
- fallback_coverage > 0 or not coverage_json_path.exists()
338
- ):
339
- current_coverage = fallback_coverage
340
- self.console.print(
341
- f"[dim]📊 Coverage from service fallback: {current_coverage:.2f}%[/dim]"
342
- )
343
- else:
314
+ def _handle_coverage_extraction_result(
315
+ self, current_coverage: float | None
316
+ ) -> float | None:
317
+ """Handle the result of coverage extraction attempts."""
318
+ if current_coverage is not None:
319
+ self.console.print(
320
+ f"[dim]📊 Coverage extracted from coverage.json: {current_coverage:.2f}%[/dim]"
321
+ )
322
+ return current_coverage
323
+
324
+ def _get_fallback_coverage(
325
+ self, ratchet_result: dict[str, t.Any], current_coverage: float | None
326
+ ) -> float | None:
327
+ """Get coverage from fallback sources."""
328
+ # Secondary: Try ratchet result if coverage.json failed
329
+ if current_coverage is None:
330
+ current_coverage = self._get_coverage_from_ratchet(ratchet_result)
331
+ if current_coverage is not None:
332
+ self.console.print(
333
+ f"[dim]📊 Coverage from ratchet result: {current_coverage:.2f}%[/dim]"
334
+ )
335
+
336
+ # Tertiary: Try coverage service, but only accept non-zero values
337
+ if current_coverage is None:
338
+ current_coverage = self._get_coverage_from_service()
339
+ if current_coverage is not None:
340
+ self.console.print(
341
+ f"[dim]📊 Coverage from service fallback: {current_coverage:.2f}%[/dim]"
342
+ )
343
+ else:
344
+ coverage_json_path = self.pkg_path / "coverage.json"
345
+ if coverage_json_path.exists():
344
346
  self.console.print(
345
347
  "[yellow]⚠️[/yellow] Skipping 0.0% fallback when coverage.json exists"
346
348
  )
347
349
 
350
+ return current_coverage
351
+
352
+ def _update_coverage_badge(self, ratchet_result: dict[str, t.Any]) -> None:
353
+ """Update coverage badge in README.md if coverage changed."""
354
+ try:
355
+ # Get current coverage directly from coverage.json to ensure freshest data
356
+ current_coverage = self._attempt_coverage_extraction()
357
+ current_coverage = self._handle_coverage_extraction_result(current_coverage)
358
+
359
+ # Get fallback coverage if needed
360
+ current_coverage = self._get_fallback_coverage(
361
+ ratchet_result, current_coverage
362
+ )
363
+
348
364
  # Only update badge if we have valid coverage data
349
365
  if current_coverage is not None and current_coverage >= 0:
350
366
  if self._coverage_badge_service.should_update_badge(current_coverage):
@@ -21,7 +21,7 @@ class AgentPerformanceMetrics:
21
21
  failed_fixes: int = 0
22
22
  average_confidence: float = 0.0
23
23
  average_execution_time: float = 0.0
24
- issue_types_handled: dict[IssueType, int] = field(default_factory=dict[str, t.Any])
24
+ issue_types_handled: dict[IssueType, int] = field(default_factory=dict)
25
25
  recent_failures: list[str] = field(default_factory=list)
26
26
  last_successful_fix: datetime | None = None
27
27
  regression_patterns: list[str] = field(default_factory=list)
@@ -1,6 +1,5 @@
1
1
  import time
2
2
  import typing as t
3
- from contextlib import suppress
4
3
  from pathlib import Path
5
4
 
6
5
  from rich.console import Console, Group
@@ -101,94 +100,47 @@ class CorrelationTracker:
101
100
  }
102
101
 
103
102
 
104
- class MinimalProgressStreamer(ProgressStreamer):
103
+ class ProgressStreamer:
104
+ """Base class for streaming progress updates during orchestration."""
105
+
105
106
  def __init__(
106
107
  self,
107
108
  config: OrchestrationConfig | None = None,
108
109
  session: SessionCoordinator | None = None,
109
110
  ) -> None:
110
- # Minimal implementation doesn't use config or session
111
- pass
111
+ self.config = config
112
+ self.session = session
112
113
 
113
114
  def update_stage(self, stage: str, substage: str = "") -> None:
115
+ """Update current stage."""
114
116
  pass
115
117
 
116
118
  def update_hook_progress(self, progress: HookProgress) -> None:
119
+ """Update hook progress."""
117
120
  pass
118
121
 
119
122
  def _stream_update(self, data: dict[str, t.Any]) -> None:
123
+ """Stream update data."""
120
124
  pass
121
125
 
122
126
 
123
- class ProgressStreamer:
127
+ class MinimalProgressStreamer(ProgressStreamer):
124
128
  def __init__(
125
129
  self,
126
- config: OrchestrationConfig,
127
- session: SessionCoordinator,
130
+ config: OrchestrationConfig | None = None,
131
+ session: SessionCoordinator | None = None,
128
132
  ) -> None:
129
- self.config = config
130
- self.session = session
131
- self.current_stage = "initialization"
132
- self.current_substage = ""
133
- self.hook_progress: dict[str, HookProgress] = {}
133
+ # Minimal implementation doesn't use config or session
134
+ pass
134
135
 
135
136
  def update_stage(self, stage: str, substage: str = "") -> None:
136
- self.current_stage = stage
137
- self.current_substage = substage
138
- self._stream_update(
139
- {
140
- "type": "stage_update",
141
- "stage": stage,
142
- "substage": substage,
143
- "timestamp": time.time(),
144
- },
145
- )
137
+ pass
146
138
 
147
139
  def update_hook_progress(self, progress: HookProgress) -> None:
148
- self.hook_progress[progress.hook_name] = progress
149
- self._stream_update(
150
- {
151
- "type": "hook_progress",
152
- "hook_name": progress.hook_name,
153
- "progress": progress.to_dict(),
154
- "timestamp": time.time(),
155
- },
156
- )
157
-
158
- def _stream_update(self, update_data: dict[str, t.Any]) -> None:
159
- self.session.update_stage(
160
- self.current_stage,
161
- f"{self.current_substage}: {update_data.get('hook_name', 'processing')}",
162
- )
163
-
164
- if hasattr(self.session, "web_job_id") and self.session.web_job_id:
165
- self._update_websocket_progress(update_data)
166
-
167
- def _update_websocket_progress(self, update_data: dict[str, t.Any]) -> None:
168
- with suppress(Exception):
169
- if hasattr(self.session, "progress_file") and self.session.progress_file:
170
- import json
171
-
172
- progress_data: dict[str, t.Any] = {}
173
- if self.session.progress_file.exists():
174
- with self.session.progress_file.open() as f:
175
- progress_data = json.load(f)
176
-
177
- progress_data.update(
178
- {
179
- "current_stage": self.current_stage,
180
- "current_substage": self.current_substage,
181
- "hook_progress": {
182
- name: prog.to_dict()
183
- for name, prog in self.hook_progress.items()
184
- },
185
- "last_update": update_data,
186
- "updated_at": time.time(),
187
- },
188
- )
140
+ pass
189
141
 
190
- with self.session.progress_file.open("w") as f:
191
- json.dump(progress_data, f, indent=2)
142
+ def _stream_update(self, data: dict[str, t.Any]) -> None:
143
+ pass
192
144
 
193
145
 
194
146
  class AdvancedWorkflowOrchestrator:
@@ -1,4 +1,4 @@
1
- import subprocess
1
+ import subprocess # nosec B404
2
2
  import typing as t
3
3
  from pathlib import Path
4
4
 
@@ -156,7 +156,7 @@ class GitService:
156
156
 
157
157
  def _retry_commit_after_restage(self, message: str) -> bool:
158
158
  self.console.print(
159
- "[yellow]🔄[/ yellow] Pre - commit hooks modified files - attempting to re-stage and retry commit"
159
+ "[yellow]🔄[/yellow] Pre-commit hooks modified files - attempting to re-stage and retry commit"
160
160
  )
161
161
 
162
162
  add_result = self._run_git_command(GIT_COMMANDS["add_updated"])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crackerjack
3
- Version: 0.38.10
3
+ Version: 0.38.11
4
4
  Summary: Crackerjack Python project management tool
5
5
  Project-URL: documentation, https://github.com/lesleslie/crackerjack
6
6
  Project-URL: homepage, https://github.com/lesleslie/crackerjack
@@ -48,7 +48,6 @@ Requires-Dist: refurb>=2.1
48
48
  Requires-Dist: rich>=14.1
49
49
  Requires-Dist: ruff>=0.12.9
50
50
  Requires-Dist: scipy>=1.14.0
51
- Requires-Dist: session-mgmt-mcp>=0.3.11
52
51
  Requires-Dist: skylos>=2.1.2
53
52
  Requires-Dist: structlog>=24.4
54
53
  Requires-Dist: textual>=0.89
@@ -75,7 +74,7 @@ Description-Content-Type: text/markdown
75
74
  [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
76
75
  [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
77
76
  [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
78
- ![Coverage](https://img.shields.io/badge/coverage-17.7%25-red)
77
+ ![Coverage](https://img.shields.io/badge/coverage-18.1%25-red)
79
78
 
80
79
  ## 🎯 Purpose
81
80
 
@@ -1,11 +1,11 @@
1
1
  crackerjack/CLAUDE.md,sha256=FnF1XgcaCB59HEZxglEl4qEBTMyHQcqKoL0YjnAq24s,41230
2
2
  crackerjack/__init__.py,sha256=DajG9zHB8qBdgdiKMumrrssUbKeMXmtIQ3oOaSTb46Y,1426
3
- crackerjack/__main__.py,sha256=cAM0ezqddeO5oC3QMr8zpUor-RN0lIG-Zja_WeatDiY,55176
3
+ crackerjack/__main__.py,sha256=hOekfMkVBYQuw294OHa8fhpuQa-E8knJh3x4KY1WxG8,55552
4
4
  crackerjack/api.py,sha256=PyCRaZHvKWdu62_2O4t_HcEfKNBdqyrfPdonS_PNn4c,21495
5
5
  crackerjack/code_cleaner.py,sha256=M1zVaq31uW0nOkPneKR8kfR3892gyyVx0VhFgRaxsj4,44338
6
6
  crackerjack/dynamic_config.py,sha256=4c8Fts9vyH8Tdon_47OFVT1iTBINSzSgB0WoeSvpzII,22418
7
7
  crackerjack/errors.py,sha256=yYbZ92kn_y6acEWgQvEPvozAYs2HT65uLwAXrtXxGsE,10049
8
- crackerjack/interactive.py,sha256=CYu53ySL2I1YCWRRRHmVEYQq3RQ0xDCXFTuPUAw6DTc,21399
8
+ crackerjack/interactive.py,sha256=t5FbxWeOErSl5kod4V8Gu5yF5yuWoZlwqlOdquOQ-vo,21943
9
9
  crackerjack/adapters/__init__.py,sha256=k-8ajMDL9DS9hV2FYOu694nmNQg3HkudJRuNcXmx8N4,451
10
10
  crackerjack/adapters/lsp_client.py,sha256=4kQ3T5JiWC7uc6kOjZuPdtUboseKSDjZpuKQpV74onc,10963
11
11
  crackerjack/adapters/rust_tool_adapter.py,sha256=ui_qMt_WIwInRvRCeT7MnIdp8eln7Fvp4hakXQiVnjg,5999
@@ -86,9 +86,9 @@ crackerjack/managers/__init__.py,sha256=PFWccXx4hDQA76T02idAViOLVD-aPeVpgjdfSkh_
86
86
  crackerjack/managers/async_hook_manager.py,sha256=c0HFR98sFwfk0uZ3NmAe_6OVZpBrq9I570V8A2DoIxw,5129
87
87
  crackerjack/managers/hook_manager.py,sha256=_FT0ngwPwujqg0KZGpLz-pP07mwDmptJ5pVkiy5yS8k,7820
88
88
  crackerjack/managers/publish_manager.py,sha256=E0jqHuscfn89pI2Ely0R6xyi3EGTvYFQeFTWyRmdjBM,22067
89
- crackerjack/managers/test_command_builder.py,sha256=O1hH4sJ4MZNr509j962Q6zzZzayKkZZSZr9AE5jUH4k,4895
89
+ crackerjack/managers/test_command_builder.py,sha256=9LWnXFOQ1nJfzbOTJNO6btIgDVc6uDHK7qiD2ol0FGI,4922
90
90
  crackerjack/managers/test_executor.py,sha256=2837Ti4OaNsmLxnmELjbQ18hmfL0-Z2EW-W2UeFSDcE,13871
91
- crackerjack/managers/test_manager.py,sha256=ClApfL9e3K1qe3vVcVbC8Y84CMJO55mwPegXiaTw9g8,18638
91
+ crackerjack/managers/test_manager.py,sha256=fiJXSIHFi_knKsOI6f8-TOTJa1jgG1TzZL6T2KYlTdM,18382
92
92
  crackerjack/managers/test_manager_backup.py,sha256=CR8D7WZ68ZrTADFqYJtVDUWnlznJXJNriPIdsp6ZB1E,37932
93
93
  crackerjack/managers/test_progress.py,sha256=B1013ygUk2nAo37whDXNA7n-FYdsEO4qj17fuDm_fdg,3058
94
94
  crackerjack/mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -135,12 +135,12 @@ crackerjack/models/protocols.py,sha256=ZtyatubJxnmnnTKzXWCbl8CvREPt2pywSco5KYBJI
135
135
  crackerjack/models/resource_protocols.py,sha256=oZiq0NEG2kWV0XQ871GIYRx_0v_oQulvEjTbidTbueM,7297
136
136
  crackerjack/models/task.py,sha256=Du5vwXj-P_aSIZsFt1Ek4jCTkXz_6DXfnflUxgXkecY,4542
137
137
  crackerjack/monitoring/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
- crackerjack/monitoring/ai_agent_watchdog.py,sha256=bc29uV9uAGFjQvL36vOtmpsYAhZCwqsOs8i1I6cmegE,15150
138
+ crackerjack/monitoring/ai_agent_watchdog.py,sha256=_Usni6d8A-1CKAx2d5LUMXYldMiQB5cdZPd-NrCe2p8,15138
139
139
  crackerjack/monitoring/metrics_collector.py,sha256=PTeOTXk07HWvPwTDK5j-Ef7LPrrNiwouz4_jw0LcP7M,15920
140
140
  crackerjack/monitoring/regression_prevention.py,sha256=hV7jwKBXjS9gBVbqHTGEr9BxtKLHkXEg6zPDgTmOeWc,20986
141
141
  crackerjack/monitoring/websocket_server.py,sha256=tmCYh5Qp58iicS_txj5OTdmt3I85M5bAGONeyrv0-EQ,24965
142
142
  crackerjack/orchestration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
143
- crackerjack/orchestration/advanced_orchestrator.py,sha256=RFvyJuUrL2-Vrii4XPX1NNtF-tcBWbbnyokqSe6sxmQ,34000
143
+ crackerjack/orchestration/advanced_orchestrator.py,sha256=05AZhCkPIiKSVVpIx7gb2_wVvGAKHv7gStu146ivcmY,32066
144
144
  crackerjack/orchestration/coverage_improvement.py,sha256=XUTUcgub0nP3vvQ8Ud5SmCYKgulEe8SAY65jbcFQzdw,6869
145
145
  crackerjack/orchestration/execution_strategies.py,sha256=M3hplgaCULMwE9TiqP9rWvivnrqdSR6DJTzY_rvueww,12482
146
146
  crackerjack/orchestration/test_progress_streamer.py,sha256=Yu6uHuhoCvX6SZP0QNG3Yt8Q4s2tufEHr40o16QU98c,22541
@@ -175,7 +175,7 @@ crackerjack/services/enterprise_optimizer.py,sha256=q6srIGxe18N9zH-MNhZ9R34sWnr_
175
175
  crackerjack/services/error_pattern_analyzer.py,sha256=YKFQi_nXx5dq-Wvi6AngKEaA-Bv5ggTQ2B2ML0AtF0c,24415
176
176
  crackerjack/services/file_hasher.py,sha256=eReytwwK-_-B8JBnpwytDC52cKKgg4qpaxaZKcQjD-0,5211
177
177
  crackerjack/services/filesystem.py,sha256=nmL3mYqylS_BSQpwFbC7EMHoA44K5qUxa9CPg1QFZvc,17480
178
- crackerjack/services/git.py,sha256=g0D9K7PFGWiv_-CbPXEhGtxJVJccEsshYNEmGstjXss,12716
178
+ crackerjack/services/git.py,sha256=E4z-hdA0UR-y5FY2A8d3fugt5Q41lonLAIt_op2Zde0,12727
179
179
  crackerjack/services/health_metrics.py,sha256=nDuKEC2a5csOhMpy6zXJkls1Y4Vfrr62-4cFcWCr8ow,21536
180
180
  crackerjack/services/heatmap_generator.py,sha256=zz5V-zXPfoCGNXoj7iuyOeFuDRRUhFpxuENUnd0X75g,26200
181
181
  crackerjack/services/initialization.py,sha256=_ZjGpIG5eGHzrVXCxlhlouhY-E-4OITEln1GDTswZ6s,26049
@@ -225,8 +225,8 @@ crackerjack/tools/validate_input_validator_patterns.py,sha256=NN7smYlXWrHLQXTb-8
225
225
  crackerjack/tools/validate_regex_patterns.py,sha256=J7GG9EP1fASpRIsG8qRPeiCSkdCwmk0sdo29GgoJ6w8,5863
226
226
  crackerjack/ui/__init__.py,sha256=eMb1OeTU-dSLICAACn0YdYB4Amdr8wHckjKfn0wOIZE,37
227
227
  crackerjack/ui/server_panels.py,sha256=F5IH6SNN06BaZQMsFx_D-OA286aojmaFPJ5kvvSRv_c,4232
228
- crackerjack-0.38.10.dist-info/METADATA,sha256=lF3_aqP8gfMzPi8Bak4nikLXGyMlZHPi1mhoAbbWm4k,38123
229
- crackerjack-0.38.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
230
- crackerjack-0.38.10.dist-info/entry_points.txt,sha256=AJKNft0WXm9xoGUJ3Trl-iXHOWxRAYbagQiza3AILr4,57
231
- crackerjack-0.38.10.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
232
- crackerjack-0.38.10.dist-info/RECORD,,
228
+ crackerjack-0.38.11.dist-info/METADATA,sha256=zlNpnIwM-e0waeO6GFqQpCowVWE4inrrE05ZSCdDk64,38083
229
+ crackerjack-0.38.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
230
+ crackerjack-0.38.11.dist-info/entry_points.txt,sha256=AJKNft0WXm9xoGUJ3Trl-iXHOWxRAYbagQiza3AILr4,57
231
+ crackerjack-0.38.11.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
232
+ crackerjack-0.38.11.dist-info/RECORD,,