crackerjack 0.31.9__py3-none-any.whl → 0.31.10__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/core/phase_coordinator.py +1 -1
- crackerjack/core/workflow_orchestrator.py +17 -0
- crackerjack/managers/test_manager.py +41 -5
- crackerjack/services/coverage_ratchet.py +9 -5
- crackerjack/services/git.py +12 -2
- crackerjack/services/initialization.py +9 -9
- {crackerjack-0.31.9.dist-info → crackerjack-0.31.10.dist-info}/METADATA +1 -1
- {crackerjack-0.31.9.dist-info → crackerjack-0.31.10.dist-info}/RECORD +11 -11
- {crackerjack-0.31.9.dist-info → crackerjack-0.31.10.dist-info}/WHEEL +0 -0
- {crackerjack-0.31.9.dist-info → crackerjack-0.31.10.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.31.9.dist-info → crackerjack-0.31.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -172,10 +172,12 @@ class WorkflowPipeline:
|
|
|
172
172
|
async def _execute_workflow_phases(self, options: OptionsProtocol) -> bool:
|
|
173
173
|
success = True
|
|
174
174
|
self.phases.run_configuration_phase(options)
|
|
175
|
+
|
|
175
176
|
if not self.phases.run_cleaning_phase(options):
|
|
176
177
|
success = False
|
|
177
178
|
self.session.fail_task("workflow", "Cleaning phase failed")
|
|
178
179
|
return False
|
|
180
|
+
|
|
179
181
|
if not await self._execute_quality_phase(options):
|
|
180
182
|
success = False
|
|
181
183
|
return False
|
|
@@ -263,6 +265,21 @@ class WorkflowPipeline:
|
|
|
263
265
|
) -> bool:
|
|
264
266
|
"""Handle standard workflow where all phases must pass."""
|
|
265
267
|
success = testing_passed and comprehensive_passed
|
|
268
|
+
|
|
269
|
+
# Debug information for workflow continuation issues
|
|
270
|
+
if not success and getattr(options, "verbose", False):
|
|
271
|
+
self.console.print(
|
|
272
|
+
f"[yellow]⚠️ Workflow stopped - testing_passed: {testing_passed}, comprehensive_passed: {comprehensive_passed}[/yellow]"
|
|
273
|
+
)
|
|
274
|
+
if not testing_passed:
|
|
275
|
+
self.console.print(
|
|
276
|
+
"[yellow] → Tests reported failure despite appearing successful[/yellow]"
|
|
277
|
+
)
|
|
278
|
+
if not comprehensive_passed:
|
|
279
|
+
self.console.print(
|
|
280
|
+
"[yellow] → Comprehensive hooks reported failure despite appearing successful[/yellow]"
|
|
281
|
+
)
|
|
282
|
+
|
|
266
283
|
if options.ai_agent and self._should_debug():
|
|
267
284
|
self.debugger.log_iteration_end(iteration, success)
|
|
268
285
|
return success
|
|
@@ -136,6 +136,36 @@ class TestManager:
|
|
|
136
136
|
except Exception:
|
|
137
137
|
return None
|
|
138
138
|
|
|
139
|
+
def get_coverage(self) -> dict[str, t.Any]:
|
|
140
|
+
"""Get coverage information as required by TestManagerProtocol."""
|
|
141
|
+
try:
|
|
142
|
+
# Get the ratchet status which includes coverage information
|
|
143
|
+
status = self.coverage_ratchet.get_status_report()
|
|
144
|
+
|
|
145
|
+
if status.get("status") == "not_initialized":
|
|
146
|
+
return {
|
|
147
|
+
"status": "not_initialized",
|
|
148
|
+
"coverage_percent": 0.0,
|
|
149
|
+
"message": "Coverage ratchet not initialized",
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
"status": "active",
|
|
154
|
+
"coverage_percent": status.get("current_coverage", 0.0),
|
|
155
|
+
"target_coverage": status.get("target_coverage", 100.0),
|
|
156
|
+
"next_milestone": status.get("next_milestone"),
|
|
157
|
+
"progress_percent": status.get("progress_percent", 0.0),
|
|
158
|
+
"last_updated": status.get("last_updated"),
|
|
159
|
+
"milestones_achieved": status.get("milestones_achieved", []),
|
|
160
|
+
}
|
|
161
|
+
except Exception as e:
|
|
162
|
+
return {
|
|
163
|
+
"status": "error",
|
|
164
|
+
"coverage_percent": 0.0,
|
|
165
|
+
"error": str(e),
|
|
166
|
+
"message": "Failed to get coverage information",
|
|
167
|
+
}
|
|
168
|
+
|
|
139
169
|
def has_tests(self) -> bool:
|
|
140
170
|
"""Check if project has tests."""
|
|
141
171
|
test_directories = ["tests", "test"]
|
|
@@ -219,11 +249,17 @@ class TestManager:
|
|
|
219
249
|
self._handle_coverage_improvement(ratchet_result)
|
|
220
250
|
return True
|
|
221
251
|
else:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
f"{ratchet_result
|
|
225
|
-
|
|
226
|
-
|
|
252
|
+
# Use the message from the ratchet result if available, or construct from available data
|
|
253
|
+
if "message" in ratchet_result:
|
|
254
|
+
self.console.print(f"[red]📉[/red] {ratchet_result['message']}")
|
|
255
|
+
else:
|
|
256
|
+
# Fallback to constructing message from available keys
|
|
257
|
+
current = ratchet_result.get("current_coverage", 0)
|
|
258
|
+
previous = ratchet_result.get("previous_coverage", 0)
|
|
259
|
+
self.console.print(
|
|
260
|
+
f"[red]📉[/red] Coverage regression: "
|
|
261
|
+
f"{current:.2f}% < {previous:.2f}%"
|
|
262
|
+
)
|
|
227
263
|
return False
|
|
228
264
|
|
|
229
265
|
def _handle_coverage_improvement(self, ratchet_result: dict[str, t.Any]) -> None:
|
|
@@ -332,11 +332,13 @@ class CoverageRatchetService:
|
|
|
332
332
|
# Look for .coverage file or coverage.json
|
|
333
333
|
coverage_file = self.pkg_path / "coverage.json"
|
|
334
334
|
if not coverage_file.exists():
|
|
335
|
-
#
|
|
335
|
+
# No coverage data - this is acceptable, return success
|
|
336
336
|
return {
|
|
337
|
-
"success":
|
|
338
|
-
"
|
|
339
|
-
"message": "
|
|
337
|
+
"success": True,
|
|
338
|
+
"status": "no_coverage_data",
|
|
339
|
+
"message": "No coverage data found - tests passed without coverage",
|
|
340
|
+
"allowed": True,
|
|
341
|
+
"baseline_updated": False,
|
|
340
342
|
}
|
|
341
343
|
|
|
342
344
|
# Parse coverage data (simplified for now)
|
|
@@ -346,7 +348,9 @@ class CoverageRatchetService:
|
|
|
346
348
|
)
|
|
347
349
|
|
|
348
350
|
# Update the ratchet
|
|
349
|
-
|
|
351
|
+
result = self.update_coverage(current_coverage)
|
|
352
|
+
result["success"] = result.get("allowed", True)
|
|
353
|
+
return result
|
|
350
354
|
|
|
351
355
|
except Exception as e:
|
|
352
356
|
return {
|
crackerjack/services/git.py
CHANGED
|
@@ -29,18 +29,27 @@ class GitService:
|
|
|
29
29
|
|
|
30
30
|
def get_changed_files(self) -> list[str]:
|
|
31
31
|
try:
|
|
32
|
-
|
|
32
|
+
# Get staged files excluding deletions
|
|
33
|
+
staged_result = self._run_git_command(
|
|
34
|
+
["diff", "--cached", "--name-only", "--diff-filter=ACMRT"]
|
|
35
|
+
)
|
|
33
36
|
staged_files = (
|
|
34
37
|
staged_result.stdout.strip().split("\n")
|
|
35
38
|
if staged_result.stdout.strip()
|
|
36
39
|
else []
|
|
37
40
|
)
|
|
38
|
-
|
|
41
|
+
|
|
42
|
+
# Get unstaged files excluding deletions
|
|
43
|
+
unstaged_result = self._run_git_command(
|
|
44
|
+
["diff", "--name-only", "--diff-filter=ACMRT"]
|
|
45
|
+
)
|
|
39
46
|
unstaged_files = (
|
|
40
47
|
unstaged_result.stdout.strip().split("\n")
|
|
41
48
|
if unstaged_result.stdout.strip()
|
|
42
49
|
else []
|
|
43
50
|
)
|
|
51
|
+
|
|
52
|
+
# Get untracked files
|
|
44
53
|
untracked_result = self._run_git_command(
|
|
45
54
|
["ls-files", "--others", "--exclude-standard"],
|
|
46
55
|
)
|
|
@@ -49,6 +58,7 @@ class GitService:
|
|
|
49
58
|
if untracked_result.stdout.strip()
|
|
50
59
|
else []
|
|
51
60
|
)
|
|
61
|
+
|
|
52
62
|
all_files = set(staged_files + unstaged_files + untracked_files)
|
|
53
63
|
return [f for f in all_files if f]
|
|
54
64
|
except Exception as e:
|
|
@@ -72,7 +72,7 @@ class InitializationService:
|
|
|
72
72
|
"pyproject.toml": "smart_merge",
|
|
73
73
|
"CLAUDE.md": "smart_append",
|
|
74
74
|
"RULES.md": "replace_if_missing",
|
|
75
|
-
"mcp.json": "special", # Special handling: mcp.json -> .mcp.json with merging
|
|
75
|
+
"example.mcp.json": "special", # Special handling: example.mcp.json -> .mcp.json with merging
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
def _process_config_file(
|
|
@@ -84,8 +84,8 @@ class InitializationService:
|
|
|
84
84
|
force: bool,
|
|
85
85
|
results: dict[str, t.Any],
|
|
86
86
|
) -> None:
|
|
87
|
-
# Special handling for mcp.json -> .mcp.json
|
|
88
|
-
if file_name == "mcp.json":
|
|
87
|
+
# Special handling for example.mcp.json -> .mcp.json
|
|
88
|
+
if file_name == "example.mcp.json":
|
|
89
89
|
self._process_mcp_config(target_path, force, results)
|
|
90
90
|
return
|
|
91
91
|
|
|
@@ -248,14 +248,14 @@ class InitializationService:
|
|
|
248
248
|
force: bool,
|
|
249
249
|
results: dict[str, t.Any],
|
|
250
250
|
) -> None:
|
|
251
|
-
"""Handle special processing for mcp.json -> .mcp.json with merging."""
|
|
252
|
-
# Source: mcp.json in crackerjack package (contains servers to add to projects)
|
|
253
|
-
source_file = self.pkg_path / "mcp.json"
|
|
251
|
+
"""Handle special processing for example.mcp.json -> .mcp.json with merging."""
|
|
252
|
+
# Source: example.mcp.json in crackerjack package (contains servers to add to projects)
|
|
253
|
+
source_file = self.pkg_path / "example.mcp.json"
|
|
254
254
|
# Target: .mcp.json in target project
|
|
255
255
|
target_file = target_path / ".mcp.json"
|
|
256
256
|
|
|
257
257
|
if not source_file.exists():
|
|
258
|
-
self._handle_missing_source_file("mcp.json", results)
|
|
258
|
+
self._handle_missing_source_file("example.mcp.json", results)
|
|
259
259
|
return
|
|
260
260
|
|
|
261
261
|
try:
|
|
@@ -265,8 +265,8 @@ class InitializationService:
|
|
|
265
265
|
|
|
266
266
|
if not isinstance(source_config.get("mcpServers"), dict):
|
|
267
267
|
self._handle_file_processing_error(
|
|
268
|
-
"mcp.json",
|
|
269
|
-
ValueError("Invalid mcp.json format: missing mcpServers"),
|
|
268
|
+
"example.mcp.json",
|
|
269
|
+
ValueError("Invalid example.mcp.json format: missing mcpServers"),
|
|
270
270
|
results,
|
|
271
271
|
)
|
|
272
272
|
return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: crackerjack
|
|
3
|
-
Version: 0.31.
|
|
3
|
+
Version: 0.31.10
|
|
4
4
|
Summary: Opinionated Python project management tool
|
|
5
5
|
Project-URL: documentation, https://github.com/lesleslie/crackerjack
|
|
6
6
|
Project-URL: homepage, https://github.com/lesleslie/crackerjack
|
|
@@ -37,10 +37,10 @@ crackerjack/core/autofix_coordinator.py,sha256=txbXTeGm-gJwuyRekVDbvvKgG0gQ1GqB3
|
|
|
37
37
|
crackerjack/core/container.py,sha256=e9_1YnWHijUJ0yl23lpgf9mennVQy8NkgJBKtZstG-M,2889
|
|
38
38
|
crackerjack/core/enhanced_container.py,sha256=fl5XvhNY0fzDnD5hSr16yQXGtL_AW01Wf4F4PL1L0P4,18169
|
|
39
39
|
crackerjack/core/performance.py,sha256=sL9g2-_JflofnsXW6LUCwp9MaUDQprfV8lSG18s9mns,7601
|
|
40
|
-
crackerjack/core/phase_coordinator.py,sha256=
|
|
40
|
+
crackerjack/core/phase_coordinator.py,sha256=L0-OXrxNDfcqSQnhyaeXot1fDk_zdHEWBl-thcbz65Y,21244
|
|
41
41
|
crackerjack/core/proactive_workflow.py,sha256=ML1amNJI4Gx0dFJK5AKdvB0zNc1chbq-ZyqnhUi4tms,12677
|
|
42
42
|
crackerjack/core/session_coordinator.py,sha256=hJKLthZBzX7fXm8AmNMFLEjITNmKxDGqM58Om6p7fr0,9893
|
|
43
|
-
crackerjack/core/workflow_orchestrator.py,sha256=
|
|
43
|
+
crackerjack/core/workflow_orchestrator.py,sha256=YHG-qp8J76fqj_poGRvTvuimljbJBvVwPT1r1OjF95M,38459
|
|
44
44
|
crackerjack/executors/__init__.py,sha256=HF-DmXvKN45uKKDdiMxOT9bYxuy1B-Z91BihOhkK5lg,322
|
|
45
45
|
crackerjack/executors/async_hook_executor.py,sha256=3U-AHToGNBojnlDsXK6HLv4CfJvv64UqTmCWYAoLcb8,15958
|
|
46
46
|
crackerjack/executors/cached_hook_executor.py,sha256=LyrFINWbixB-0xEnaU0F2ZUBFUWrAdaTKvj_JW1Wss0,8186
|
|
@@ -58,7 +58,7 @@ crackerjack/managers/hook_manager.py,sha256=3qAKLYqoJGPJ8NAUB1KEoWHZafjs6564P9ud
|
|
|
58
58
|
crackerjack/managers/publish_manager.py,sha256=7bBXkaHm1Ou-tMLvUqNQZScp_onZ2SJgB0o3kwThUDE,16084
|
|
59
59
|
crackerjack/managers/test_command_builder.py,sha256=MdDz9AYSLOoLmI-8zoq3zd2SXF3DeuIkANa76h9cINI,5295
|
|
60
60
|
crackerjack/managers/test_executor.py,sha256=XCMuJPssTV2Glb0hDPHvoDbVrJHVJpZrsAIltegMMfE,16337
|
|
61
|
-
crackerjack/managers/test_manager.py,sha256=
|
|
61
|
+
crackerjack/managers/test_manager.py,sha256=4HfnkWy2Sqbu-YW9zkIK0UNc1bnk0SUspK0ldg5RFGI,11387
|
|
62
62
|
crackerjack/managers/test_manager_backup.py,sha256=tptpX99nw-caLJMVga4Hss7grJRqcFHz1JkRBqro4sE,41307
|
|
63
63
|
crackerjack/managers/test_progress.py,sha256=gCNKdE7Bh7RS3K7Ekj2MGKCqiY4px54AzPNi0gMhAL0,3908
|
|
64
64
|
crackerjack/mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -117,15 +117,15 @@ crackerjack/services/cache.py,sha256=LKZIa8xZ6SzwdTBttO1W6VEBxaTgMNI5Paz_IgrqoaI
|
|
|
117
117
|
crackerjack/services/config.py,sha256=BrIJoKKi0qyQg2lcZZhTTUpAVB6ej6gkbPv95o2rVvc,14050
|
|
118
118
|
crackerjack/services/config_integrity.py,sha256=wn6b0x90wXNRSj64J_kOQ5JMQvG_9FwtOno0ITVJGwM,3416
|
|
119
119
|
crackerjack/services/contextual_ai_assistant.py,sha256=QnJvJNdGimk-u6XxPm9D7F516AmbueNnAmky42D2caQ,19206
|
|
120
|
-
crackerjack/services/coverage_ratchet.py,sha256=
|
|
120
|
+
crackerjack/services/coverage_ratchet.py,sha256=XM4iCe_Bckh1j378FgAG2zlbiJNCF0VeH1qVWG-fu1s,13731
|
|
121
121
|
crackerjack/services/debug.py,sha256=crjsUZwVjP92aCEOEmtpEJwNf5gtlwNeZF_eB9JSfiI,24018
|
|
122
122
|
crackerjack/services/dependency_monitor.py,sha256=axBXFGBdezoPK9ph5_ZGxIwhSJhurgdvCSiuaCWSrKY,21085
|
|
123
123
|
crackerjack/services/enhanced_filesystem.py,sha256=MQj5zqvkNc5U6ZUmSVzgFQWKfnizD1lv4SJ2pt-w8W4,15424
|
|
124
124
|
crackerjack/services/file_hasher.py,sha256=vHSJ6QbWU5Q5JPLYuQkyRMRXCpDC_hsxToaM83vI58U,5201
|
|
125
125
|
crackerjack/services/filesystem.py,sha256=Re5VyP7H8W6T2tpDakoaghEivdR2VmshJgnZ9Y3QkH8,17932
|
|
126
|
-
crackerjack/services/git.py,sha256=
|
|
126
|
+
crackerjack/services/git.py,sha256=ZsIrsYhTuDyRSz4Lhtvh2cEFose7EPSpuDg74Vh8npI,8613
|
|
127
127
|
crackerjack/services/health_metrics.py,sha256=M2OBqwwnGvnJB3eXIXXh5SgMuckYCjHIrD0RkYFAbQU,21458
|
|
128
|
-
crackerjack/services/initialization.py,sha256=
|
|
128
|
+
crackerjack/services/initialization.py,sha256=l3CagjRvBD9AQWkzD_JWQciSCQpYOPduRkPdUprE6MA,33455
|
|
129
129
|
crackerjack/services/log_manager.py,sha256=deM_i97biZVyuZJoHaGlnBitc5QV4WaaZHEb70N5LV0,8388
|
|
130
130
|
crackerjack/services/logging.py,sha256=c15gVCLR_yRhqaza7f1pLLYL-xQ3Oi_OMWL_mR5G46k,5354
|
|
131
131
|
crackerjack/services/metrics.py,sha256=kInkb2G0ML8hAtmEG1jK04b-F1hT_fZjHvYJKisyr1Y,22894
|
|
@@ -142,8 +142,8 @@ crackerjack/slash_commands/__init__.py,sha256=ZHfKjluj9dX88zDYN6Saj7tGUMdMnh37Q8
|
|
|
142
142
|
crackerjack/slash_commands/init.md,sha256=mANRdCiFAzaTw29lKNrI1JFthK4pxVdtiFC5lN2SDSQ,4581
|
|
143
143
|
crackerjack/slash_commands/run.md,sha256=bf_mEtnXagUuw3w8os5h3t1Yi3vjpfiNbkMJvuFEu-Y,6500
|
|
144
144
|
crackerjack/slash_commands/status.md,sha256=U3qqppVLtIIm2lEiMYaKagaHYLI9UplL7OH1j6SRJGw,3921
|
|
145
|
-
crackerjack-0.31.
|
|
146
|
-
crackerjack-0.31.
|
|
147
|
-
crackerjack-0.31.
|
|
148
|
-
crackerjack-0.31.
|
|
149
|
-
crackerjack-0.31.
|
|
145
|
+
crackerjack-0.31.10.dist-info/METADATA,sha256=4VBwoRFPEEXi1M6Lh6wY7wCEFTAmVKnyRowdCjDT4V8,22438
|
|
146
|
+
crackerjack-0.31.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
147
|
+
crackerjack-0.31.10.dist-info/entry_points.txt,sha256=AJKNft0WXm9xoGUJ3Trl-iXHOWxRAYbagQiza3AILr4,57
|
|
148
|
+
crackerjack-0.31.10.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
|
|
149
|
+
crackerjack-0.31.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|