claude-task-master 0.1.8__py3-none-any.whl → 0.1.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.
- claude_task_master/__init__.py +1 -1
- claude_task_master/api/models.py +43 -5
- claude_task_master/api/routes.py +69 -1
- claude_task_master/cli_commands/workflow.py +8 -0
- claude_task_master/core/agent.py +7 -2
- claude_task_master/core/agent_message.py +18 -3
- claude_task_master/core/agent_phases.py +7 -1
- claude_task_master/core/orchestrator.py +131 -23
- claude_task_master/core/planner.py +8 -2
- claude_task_master/core/prompts_planning.py +27 -1
- claude_task_master/core/state.py +1 -0
- claude_task_master/core/state_file_ops.py +12 -0
- claude_task_master/mcp/server.py +25 -1
- claude_task_master/mcp/tools.py +67 -0
- claude_task_master/webhooks/events.py +2 -2
- {claude_task_master-0.1.8.dist-info → claude_task_master-0.1.10.dist-info}/METADATA +16 -7
- {claude_task_master-0.1.8.dist-info → claude_task_master-0.1.10.dist-info}/RECORD +20 -20
- {claude_task_master-0.1.8.dist-info → claude_task_master-0.1.10.dist-info}/WHEEL +1 -1
- {claude_task_master-0.1.8.dist-info → claude_task_master-0.1.10.dist-info}/entry_points.txt +0 -0
- {claude_task_master-0.1.8.dist-info → claude_task_master-0.1.10.dist-info}/top_level.txt +0 -0
claude_task_master/__init__.py
CHANGED
claude_task_master/api/models.py
CHANGED
|
@@ -25,6 +25,7 @@ Response Models:
|
|
|
25
25
|
- CloneRepoResponse: Result of cloning a repository
|
|
26
26
|
- SetupRepoResponse: Result of setting up a repository
|
|
27
27
|
- PlanRepoResponse: Result of planning for a repository
|
|
28
|
+
- DeleteCodingStyleResponse: Result of deleting coding-style.md
|
|
28
29
|
|
|
29
30
|
Usage:
|
|
30
31
|
from claude_task_master.api.models import (
|
|
@@ -47,7 +48,7 @@ Usage:
|
|
|
47
48
|
from __future__ import annotations
|
|
48
49
|
|
|
49
50
|
from datetime import datetime
|
|
50
|
-
from enum import Enum
|
|
51
|
+
from enum import Enum, StrEnum
|
|
51
52
|
from typing import Any
|
|
52
53
|
|
|
53
54
|
from pydantic import BaseModel, Field
|
|
@@ -57,7 +58,7 @@ from pydantic import BaseModel, Field
|
|
|
57
58
|
# =============================================================================
|
|
58
59
|
|
|
59
60
|
|
|
60
|
-
class TaskStatus(
|
|
61
|
+
class TaskStatus(StrEnum):
|
|
61
62
|
"""Valid task status values."""
|
|
62
63
|
|
|
63
64
|
PLANNING = "planning"
|
|
@@ -69,7 +70,7 @@ class TaskStatus(str, Enum):
|
|
|
69
70
|
FAILED = "failed"
|
|
70
71
|
|
|
71
72
|
|
|
72
|
-
class WorkflowStage(
|
|
73
|
+
class WorkflowStage(StrEnum):
|
|
73
74
|
"""Valid workflow stage values for PR lifecycle."""
|
|
74
75
|
|
|
75
76
|
WORKING = "working"
|
|
@@ -82,7 +83,7 @@ class WorkflowStage(str, Enum):
|
|
|
82
83
|
MERGED = "merged"
|
|
83
84
|
|
|
84
85
|
|
|
85
|
-
class LogLevel(
|
|
86
|
+
class LogLevel(StrEnum):
|
|
86
87
|
"""Valid log level values."""
|
|
87
88
|
|
|
88
89
|
QUIET = "quiet"
|
|
@@ -90,7 +91,7 @@ class LogLevel(str, Enum):
|
|
|
90
91
|
VERBOSE = "verbose"
|
|
91
92
|
|
|
92
93
|
|
|
93
|
-
class LogFormat(
|
|
94
|
+
class LogFormat(StrEnum):
|
|
94
95
|
"""Valid log format values."""
|
|
95
96
|
|
|
96
97
|
TEXT = "text"
|
|
@@ -158,6 +159,7 @@ class ConfigUpdateRequest(BaseModel):
|
|
|
158
159
|
Attributes:
|
|
159
160
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
160
161
|
max_sessions: Maximum number of work sessions before pausing.
|
|
162
|
+
max_prs: Maximum number of pull requests to create.
|
|
161
163
|
pause_on_pr: Whether to pause after creating PR for manual review.
|
|
162
164
|
enable_checkpointing: Whether to enable state checkpointing.
|
|
163
165
|
log_level: Log level (quiet, normal, verbose).
|
|
@@ -175,6 +177,12 @@ class ConfigUpdateRequest(BaseModel):
|
|
|
175
177
|
le=1000,
|
|
176
178
|
description="Maximum number of work sessions before pausing",
|
|
177
179
|
)
|
|
180
|
+
max_prs: int | None = Field(
|
|
181
|
+
default=None,
|
|
182
|
+
ge=1,
|
|
183
|
+
le=100,
|
|
184
|
+
description="Maximum number of pull requests to create",
|
|
185
|
+
)
|
|
178
186
|
pause_on_pr: bool | None = Field(
|
|
179
187
|
default=None,
|
|
180
188
|
description="Whether to pause after creating PR for manual review",
|
|
@@ -227,6 +235,7 @@ class TaskInitRequest(BaseModel):
|
|
|
227
235
|
model: Model to use (opus, sonnet, haiku).
|
|
228
236
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
229
237
|
max_sessions: Max work sessions before pausing.
|
|
238
|
+
max_prs: Max pull requests to create.
|
|
230
239
|
pause_on_pr: Pause after creating PR for manual review.
|
|
231
240
|
"""
|
|
232
241
|
|
|
@@ -252,6 +261,12 @@ class TaskInitRequest(BaseModel):
|
|
|
252
261
|
le=1000,
|
|
253
262
|
description="Maximum number of work sessions before pausing",
|
|
254
263
|
)
|
|
264
|
+
max_prs: int | None = Field(
|
|
265
|
+
default=None,
|
|
266
|
+
ge=1,
|
|
267
|
+
le=100,
|
|
268
|
+
description="Maximum number of pull requests to create",
|
|
269
|
+
)
|
|
255
270
|
pause_on_pr: bool = Field(
|
|
256
271
|
default=False,
|
|
257
272
|
description="Pause after creating PR for manual review",
|
|
@@ -383,6 +398,7 @@ class TaskOptionsResponse(BaseModel):
|
|
|
383
398
|
Attributes:
|
|
384
399
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
385
400
|
max_sessions: Maximum number of work sessions before pausing.
|
|
401
|
+
max_prs: Maximum number of pull requests to create.
|
|
386
402
|
pause_on_pr: Whether to pause after creating PR for manual review.
|
|
387
403
|
enable_checkpointing: Whether state checkpointing is enabled.
|
|
388
404
|
log_level: Current log level.
|
|
@@ -392,6 +408,7 @@ class TaskOptionsResponse(BaseModel):
|
|
|
392
408
|
|
|
393
409
|
auto_merge: bool
|
|
394
410
|
max_sessions: int | None
|
|
411
|
+
max_prs: int | None
|
|
395
412
|
pause_on_pr: bool
|
|
396
413
|
enable_checkpointing: bool
|
|
397
414
|
log_level: str
|
|
@@ -860,3 +877,24 @@ class PlanRepoResponse(BaseModel):
|
|
|
860
877
|
criteria: str | None = None
|
|
861
878
|
run_id: str | None = None
|
|
862
879
|
error: str | None = None
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
# =============================================================================
|
|
883
|
+
# Coding Style Response Models
|
|
884
|
+
# =============================================================================
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
class DeleteCodingStyleResponse(BaseModel):
|
|
888
|
+
"""Response model for deleting the coding-style.md file.
|
|
889
|
+
|
|
890
|
+
Attributes:
|
|
891
|
+
success: Whether the deletion operation succeeded.
|
|
892
|
+
message: Human-readable result message.
|
|
893
|
+
file_existed: Whether the file existed before deletion.
|
|
894
|
+
error: Error message if deletion failed.
|
|
895
|
+
"""
|
|
896
|
+
|
|
897
|
+
success: bool
|
|
898
|
+
message: str
|
|
899
|
+
file_existed: bool = False
|
|
900
|
+
error: str | None = None
|
claude_task_master/api/routes.py
CHANGED
|
@@ -10,6 +10,7 @@ Endpoints:
|
|
|
10
10
|
- GET /progress: Get progress summary
|
|
11
11
|
- GET /context: Get accumulated context/learnings
|
|
12
12
|
- GET /health: Health check endpoint
|
|
13
|
+
- DELETE /coding-style: Delete the coding-style.md file
|
|
13
14
|
- POST /task/init: Initialize a new task
|
|
14
15
|
- DELETE /task: Delete/cleanup current task
|
|
15
16
|
- POST /control/stop: Stop a running task with optional cleanup
|
|
@@ -51,6 +52,7 @@ from claude_task_master.api.models import (
|
|
|
51
52
|
ConfigUpdateRequest,
|
|
52
53
|
ContextResponse,
|
|
53
54
|
ControlResponse,
|
|
55
|
+
DeleteCodingStyleResponse,
|
|
54
56
|
ErrorResponse,
|
|
55
57
|
HealthResponse,
|
|
56
58
|
LogsResponse,
|
|
@@ -285,6 +287,7 @@ def create_info_router() -> APIRouter:
|
|
|
285
287
|
options=TaskOptionsResponse(
|
|
286
288
|
auto_merge=state.options.auto_merge,
|
|
287
289
|
max_sessions=state.options.max_sessions,
|
|
290
|
+
max_prs=state.options.max_prs,
|
|
288
291
|
pause_on_pr=state.options.pause_on_pr,
|
|
289
292
|
enable_checkpointing=state.options.enable_checkpointing,
|
|
290
293
|
log_level=state.options.log_level,
|
|
@@ -613,6 +616,68 @@ def create_info_router() -> APIRouter:
|
|
|
613
616
|
active_tasks=active_tasks,
|
|
614
617
|
)
|
|
615
618
|
|
|
619
|
+
@router.delete(
|
|
620
|
+
"/coding-style",
|
|
621
|
+
response_model=DeleteCodingStyleResponse,
|
|
622
|
+
responses={
|
|
623
|
+
404: {"model": ErrorResponse, "description": "No active task found"},
|
|
624
|
+
500: {"model": ErrorResponse, "description": "Internal server error"},
|
|
625
|
+
},
|
|
626
|
+
summary="Delete Coding Style",
|
|
627
|
+
description="Delete the coding-style.md file from the state directory.",
|
|
628
|
+
)
|
|
629
|
+
async def delete_coding_style(request: Request) -> DeleteCodingStyleResponse | JSONResponse:
|
|
630
|
+
"""Delete the coding-style.md file.
|
|
631
|
+
|
|
632
|
+
Removes the coding-style.md file from the state directory. This file
|
|
633
|
+
contains extracted coding conventions and is regenerated on the next run.
|
|
634
|
+
|
|
635
|
+
Returns:
|
|
636
|
+
DeleteCodingStyleResponse indicating whether the file was deleted.
|
|
637
|
+
|
|
638
|
+
Raises:
|
|
639
|
+
404: If no active task exists.
|
|
640
|
+
500: If an error occurs during deletion.
|
|
641
|
+
"""
|
|
642
|
+
state_manager = _get_state_manager(request)
|
|
643
|
+
|
|
644
|
+
if not state_manager.exists():
|
|
645
|
+
return JSONResponse(
|
|
646
|
+
status_code=404,
|
|
647
|
+
content=ErrorResponse(
|
|
648
|
+
error="not_found",
|
|
649
|
+
message="No active task found",
|
|
650
|
+
suggestion="Start a new task with 'claudetm start <goal>'",
|
|
651
|
+
).model_dump(),
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
try:
|
|
655
|
+
file_existed = state_manager.delete_coding_style()
|
|
656
|
+
|
|
657
|
+
if file_existed:
|
|
658
|
+
return DeleteCodingStyleResponse(
|
|
659
|
+
success=True,
|
|
660
|
+
message="Coding style file deleted successfully",
|
|
661
|
+
file_existed=True,
|
|
662
|
+
)
|
|
663
|
+
else:
|
|
664
|
+
return DeleteCodingStyleResponse(
|
|
665
|
+
success=True,
|
|
666
|
+
message="Coding style file did not exist",
|
|
667
|
+
file_existed=False,
|
|
668
|
+
)
|
|
669
|
+
|
|
670
|
+
except Exception as e:
|
|
671
|
+
logger.exception("Error deleting coding style file")
|
|
672
|
+
return JSONResponse(
|
|
673
|
+
status_code=500,
|
|
674
|
+
content=ErrorResponse(
|
|
675
|
+
error="internal_error",
|
|
676
|
+
message="Failed to delete coding style file",
|
|
677
|
+
detail=str(e),
|
|
678
|
+
).model_dump(),
|
|
679
|
+
)
|
|
680
|
+
|
|
616
681
|
return router
|
|
617
682
|
|
|
618
683
|
|
|
@@ -1004,6 +1069,7 @@ def create_task_router() -> APIRouter:
|
|
|
1004
1069
|
options = TaskOptions(
|
|
1005
1070
|
auto_merge=task_init.auto_merge,
|
|
1006
1071
|
max_sessions=task_init.max_sessions,
|
|
1072
|
+
max_prs=task_init.max_prs,
|
|
1007
1073
|
pause_on_pr=task_init.pause_on_pr,
|
|
1008
1074
|
enable_checkpointing=False, # Default to False
|
|
1009
1075
|
log_level="normal", # Default to normal
|
|
@@ -1356,7 +1422,9 @@ def register_routes(app: FastAPI) -> None:
|
|
|
1356
1422
|
repo_router = create_repo_router()
|
|
1357
1423
|
app.include_router(repo_router, prefix="/repo")
|
|
1358
1424
|
|
|
1359
|
-
logger.debug(
|
|
1425
|
+
logger.debug(
|
|
1426
|
+
"Registered info routes: /status, /plan, /logs, /progress, /context, /health, /coding-style"
|
|
1427
|
+
)
|
|
1360
1428
|
logger.debug("Registered control routes: /control/stop, /control/resume, /config")
|
|
1361
1429
|
logger.debug("Registered task routes: /task/init, /task")
|
|
1362
1430
|
logger.debug("Registered webhook routes: /webhooks, /webhooks/{id}, /webhooks/test")
|
|
@@ -113,6 +113,11 @@ def start(
|
|
|
113
113
|
"-n",
|
|
114
114
|
help="Max work sessions before pausing (default: unlimited)",
|
|
115
115
|
),
|
|
116
|
+
max_prs: int | None = typer.Option(
|
|
117
|
+
None,
|
|
118
|
+
"--prs",
|
|
119
|
+
help="Max pull requests to create (default: unlimited)",
|
|
120
|
+
),
|
|
116
121
|
pause_on_pr: bool = typer.Option(
|
|
117
122
|
False,
|
|
118
123
|
"--pause-on-pr",
|
|
@@ -158,6 +163,8 @@ def start(
|
|
|
158
163
|
claudetm start "Add dark mode toggle"
|
|
159
164
|
claudetm start "Fix bug #123" -m opus --no-auto-merge
|
|
160
165
|
claudetm start "Refactor auth" -n 5 --pause-on-pr
|
|
166
|
+
claudetm start "Add user auth" --prs 1
|
|
167
|
+
claudetm start "Implement dashboard" --prs 3 --max-sessions 10
|
|
161
168
|
claudetm start "Debug issue" -l verbose --log-format json
|
|
162
169
|
claudetm start "Deploy feature" --webhook-url https://example.com/hooks
|
|
163
170
|
|
|
@@ -212,6 +219,7 @@ def start(
|
|
|
212
219
|
options = TaskOptions(
|
|
213
220
|
auto_merge=auto_merge,
|
|
214
221
|
max_sessions=max_sessions,
|
|
222
|
+
max_prs=max_prs,
|
|
215
223
|
pause_on_pr=pause_on_pr,
|
|
216
224
|
enable_checkpointing=enable_checkpointing,
|
|
217
225
|
log_level=log_level.lower(),
|
claude_task_master/core/agent.py
CHANGED
|
@@ -171,7 +171,11 @@ class AgentWrapper:
|
|
|
171
171
|
)
|
|
172
172
|
|
|
173
173
|
def run_planning_phase(
|
|
174
|
-
self,
|
|
174
|
+
self,
|
|
175
|
+
goal: str,
|
|
176
|
+
context: str = "",
|
|
177
|
+
coding_style: str | None = None,
|
|
178
|
+
max_prs: int | None = None,
|
|
175
179
|
) -> dict[str, Any]:
|
|
176
180
|
"""Run planning phase with read-only tools.
|
|
177
181
|
|
|
@@ -182,10 +186,11 @@ class AgentWrapper:
|
|
|
182
186
|
goal: The goal to plan for.
|
|
183
187
|
context: Additional context for planning.
|
|
184
188
|
coding_style: Optional coding style guide to inject into prompt.
|
|
189
|
+
max_prs: Optional maximum number of PRs to create.
|
|
185
190
|
|
|
186
191
|
Delegates to AgentPhaseExecutor for implementation.
|
|
187
192
|
"""
|
|
188
|
-
return self._phase_executor.run_planning_phase(goal, context, coding_style)
|
|
193
|
+
return self._phase_executor.run_planning_phase(goal, context, coding_style, max_prs)
|
|
189
194
|
|
|
190
195
|
def generate_coding_style(self) -> dict[str, Any]:
|
|
191
196
|
"""Generate a coding style guide by analyzing the codebase.
|
|
@@ -79,10 +79,25 @@ class MessageProcessor:
|
|
|
79
79
|
self.logger.log_tool_result(block.tool_use_id, "completed")
|
|
80
80
|
|
|
81
81
|
# Collect final result from ResultMessage
|
|
82
|
+
# Important: Only use message.result if we have no accumulated text,
|
|
83
|
+
# or if message.result contains content not in our accumulated text.
|
|
84
|
+
# This preserves verification markers (VERIFICATION_RESULT: PASS/FAIL)
|
|
85
|
+
# that may be output in earlier TextBlocks.
|
|
82
86
|
if message_type == "ResultMessage":
|
|
83
|
-
if hasattr(message, "result"):
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
if hasattr(message, "result") and message.result:
|
|
88
|
+
# If we have no accumulated text, use the result
|
|
89
|
+
if not result_text.strip():
|
|
90
|
+
result_text = message.result
|
|
91
|
+
console.newline() # Add newline after completion
|
|
92
|
+
# If message.result contains verification markers we're missing,
|
|
93
|
+
# prefer message.result (it might be more complete)
|
|
94
|
+
elif (
|
|
95
|
+
"verification_result:" in message.result.lower()
|
|
96
|
+
and "verification_result:" not in result_text.lower()
|
|
97
|
+
):
|
|
98
|
+
result_text = message.result
|
|
99
|
+
console.newline() # Add newline after completion
|
|
100
|
+
# Otherwise keep our accumulated text (it has the markers)
|
|
86
101
|
|
|
87
102
|
return result_text
|
|
88
103
|
|
|
@@ -111,7 +111,11 @@ class AgentPhaseExecutor:
|
|
|
111
111
|
self.process_message_func = process_message_func
|
|
112
112
|
|
|
113
113
|
def run_planning_phase(
|
|
114
|
-
self,
|
|
114
|
+
self,
|
|
115
|
+
goal: str,
|
|
116
|
+
context: str = "",
|
|
117
|
+
coding_style: str | None = None,
|
|
118
|
+
max_prs: int | None = None,
|
|
115
119
|
) -> dict[str, Any]:
|
|
116
120
|
"""Run planning phase with read-only tools.
|
|
117
121
|
|
|
@@ -122,6 +126,7 @@ class AgentPhaseExecutor:
|
|
|
122
126
|
goal: The goal to plan for.
|
|
123
127
|
context: Additional context for planning.
|
|
124
128
|
coding_style: Optional coding style guide to inject into prompt.
|
|
129
|
+
max_prs: Optional maximum number of PRs to create.
|
|
125
130
|
|
|
126
131
|
Returns:
|
|
127
132
|
Dict with 'plan', 'criteria', and 'raw_output' keys.
|
|
@@ -131,6 +136,7 @@ class AgentPhaseExecutor:
|
|
|
131
136
|
goal=goal,
|
|
132
137
|
context=context if context else None,
|
|
133
138
|
coding_style=coding_style,
|
|
139
|
+
max_prs=max_prs,
|
|
134
140
|
)
|
|
135
141
|
|
|
136
142
|
# Always use Opus for planning (smartest model)
|
|
@@ -1357,6 +1357,9 @@ After completing your fixes, end with: TASK COMPLETE"""
|
|
|
1357
1357
|
def _wait_for_fix_pr_merge(self, state: TaskState) -> bool:
|
|
1358
1358
|
"""Wait for fix PR to pass CI and merge it.
|
|
1359
1359
|
|
|
1360
|
+
If CI fails, attempts to fix the issues (up to 2 retries) before giving up.
|
|
1361
|
+
This mirrors the regular PR workflow where CI failures trigger fix sessions.
|
|
1362
|
+
|
|
1360
1363
|
Args:
|
|
1361
1364
|
state: Current task state.
|
|
1362
1365
|
|
|
@@ -1377,7 +1380,68 @@ After completing your fixes, end with: TASK COMPLETE"""
|
|
|
1377
1380
|
console.warning(f"Could not detect fix PR: {e}")
|
|
1378
1381
|
return False
|
|
1379
1382
|
|
|
1380
|
-
#
|
|
1383
|
+
# Allow up to 2 CI fix attempts before giving up
|
|
1384
|
+
max_ci_fix_attempts = 1 # 0 and 1 = 2 attempts
|
|
1385
|
+
ci_fix_attempt = 0
|
|
1386
|
+
|
|
1387
|
+
while ci_fix_attempt <= max_ci_fix_attempts:
|
|
1388
|
+
# Poll CI until success or failure
|
|
1389
|
+
ci_result = self._poll_fix_pr_ci(pr_number, state)
|
|
1390
|
+
|
|
1391
|
+
if ci_result == "success":
|
|
1392
|
+
# CI passed, proceed to merge
|
|
1393
|
+
break
|
|
1394
|
+
elif ci_result == "failure":
|
|
1395
|
+
ci_fix_attempt += 1
|
|
1396
|
+
if ci_fix_attempt > max_ci_fix_attempts:
|
|
1397
|
+
console.error(f"Fix PR CI failed after {max_ci_fix_attempts} fix attempts")
|
|
1398
|
+
return False
|
|
1399
|
+
|
|
1400
|
+
# Attempt to fix the CI failure
|
|
1401
|
+
console.info(
|
|
1402
|
+
f"Attempting to fix CI failure ({ci_fix_attempt}/{max_ci_fix_attempts})..."
|
|
1403
|
+
)
|
|
1404
|
+
if not self._fix_pr_ci_failure(pr_number, state):
|
|
1405
|
+
console.error("Failed to fix CI issues")
|
|
1406
|
+
return False
|
|
1407
|
+
|
|
1408
|
+
# Wait for CI to restart after push
|
|
1409
|
+
console.info("Waiting 30s for CI to restart...")
|
|
1410
|
+
if not interruptible_sleep(30):
|
|
1411
|
+
return False
|
|
1412
|
+
else:
|
|
1413
|
+
# Interrupted or timed out
|
|
1414
|
+
return False
|
|
1415
|
+
|
|
1416
|
+
# Merge the PR
|
|
1417
|
+
if state.options.auto_merge:
|
|
1418
|
+
try:
|
|
1419
|
+
console.info(f"Merging fix PR #{pr_number}...")
|
|
1420
|
+
self.github_client.merge_pr(pr_number)
|
|
1421
|
+
console.success(f"Fix PR #{pr_number} merged!")
|
|
1422
|
+
|
|
1423
|
+
# Checkout back to target branch
|
|
1424
|
+
self._checkout_to_main()
|
|
1425
|
+
|
|
1426
|
+
return True
|
|
1427
|
+
except Exception as e:
|
|
1428
|
+
console.error(f"Failed to merge fix PR: {e}")
|
|
1429
|
+
return False
|
|
1430
|
+
else:
|
|
1431
|
+
console.info(f"Fix PR #{pr_number} ready to merge (auto_merge disabled)")
|
|
1432
|
+
console.detail("Merge manually then run 'claudetm resume'")
|
|
1433
|
+
return False
|
|
1434
|
+
|
|
1435
|
+
def _poll_fix_pr_ci(self, pr_number: int, state: TaskState) -> str:
|
|
1436
|
+
"""Poll CI status for a fix PR.
|
|
1437
|
+
|
|
1438
|
+
Args:
|
|
1439
|
+
pr_number: The PR number to check.
|
|
1440
|
+
state: Current task state.
|
|
1441
|
+
|
|
1442
|
+
Returns:
|
|
1443
|
+
"success" if CI passed, "failure" if CI failed, "interrupted" if cancelled.
|
|
1444
|
+
"""
|
|
1381
1445
|
max_wait = 600 # 10 minutes max
|
|
1382
1446
|
poll_interval = 10
|
|
1383
1447
|
waited = 0
|
|
@@ -1388,40 +1452,84 @@ After completing your fixes, end with: TASK COMPLETE"""
|
|
|
1388
1452
|
|
|
1389
1453
|
if pr_status.ci_state == "SUCCESS":
|
|
1390
1454
|
console.success("Fix PR CI passed!")
|
|
1391
|
-
|
|
1455
|
+
return "success"
|
|
1392
1456
|
elif pr_status.ci_state in ("FAILURE", "ERROR"):
|
|
1393
|
-
console.
|
|
1394
|
-
return
|
|
1457
|
+
console.warning("Fix PR CI failed")
|
|
1458
|
+
return "failure"
|
|
1395
1459
|
else:
|
|
1396
1460
|
console.info(f"Waiting for fix PR CI... ({pr_status.checks_pending} pending)")
|
|
1397
1461
|
if not interruptible_sleep(poll_interval):
|
|
1398
|
-
return
|
|
1462
|
+
return "interrupted"
|
|
1399
1463
|
waited += poll_interval
|
|
1400
1464
|
except Exception as e:
|
|
1401
1465
|
console.warning(f"Error checking CI: {e}")
|
|
1402
1466
|
if not interruptible_sleep(poll_interval):
|
|
1403
|
-
return
|
|
1467
|
+
return "interrupted"
|
|
1404
1468
|
waited += poll_interval
|
|
1405
1469
|
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
return False
|
|
1470
|
+
console.warning("Timed out waiting for fix PR CI")
|
|
1471
|
+
return "interrupted"
|
|
1409
1472
|
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
try:
|
|
1413
|
-
console.info(f"Merging fix PR #{pr_number}...")
|
|
1414
|
-
self.github_client.merge_pr(pr_number)
|
|
1415
|
-
console.success(f"Fix PR #{pr_number} merged!")
|
|
1473
|
+
def _fix_pr_ci_failure(self, pr_number: int, state: TaskState) -> bool:
|
|
1474
|
+
"""Fix CI failures on a fix PR.
|
|
1416
1475
|
|
|
1417
|
-
|
|
1418
|
-
self._checkout_to_main()
|
|
1476
|
+
Saves CI failure logs and runs an agent to fix the issues.
|
|
1419
1477
|
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1478
|
+
Args:
|
|
1479
|
+
pr_number: The PR number with failing CI.
|
|
1480
|
+
state: Current task state.
|
|
1481
|
+
|
|
1482
|
+
Returns:
|
|
1483
|
+
True if fix session completed successfully.
|
|
1484
|
+
"""
|
|
1485
|
+
try:
|
|
1486
|
+
# Save CI failure logs
|
|
1487
|
+
self.pr_context.save_ci_failures(pr_number)
|
|
1488
|
+
|
|
1489
|
+
# Get feedback (CI failures)
|
|
1490
|
+
has_ci, has_comments, pr_dir_path = self.pr_context.get_combined_feedback(pr_number)
|
|
1491
|
+
|
|
1492
|
+
if not has_ci and not has_comments:
|
|
1493
|
+
console.warning("No CI failures or comments found to fix")
|
|
1423
1494
|
return False
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1495
|
+
|
|
1496
|
+
# Build task description
|
|
1497
|
+
ci_path = f"{pr_dir_path}/ci/" if pr_dir_path else ".claude-task-master/debugging/"
|
|
1498
|
+
|
|
1499
|
+
task_description = f"""
|
|
1500
|
+
Fix PR CI Failure
|
|
1501
|
+
|
|
1502
|
+
The CI checks have failed for this fix PR. Your task is to:
|
|
1503
|
+
|
|
1504
|
+
1. Read the CI failure logs in `{ci_path}`
|
|
1505
|
+
2. Understand what tests/lints are failing
|
|
1506
|
+
3. Fix the issues in the codebase
|
|
1507
|
+
4. Run tests locally to verify fixes (check package.json, Makefile, or pyproject.toml for test commands)
|
|
1508
|
+
5. Commit and push the fixes
|
|
1509
|
+
|
|
1510
|
+
Important:
|
|
1511
|
+
- Only fix issues identified in the CI logs
|
|
1512
|
+
- Run tests locally before committing
|
|
1513
|
+
- Push changes to trigger a new CI run
|
|
1514
|
+
"""
|
|
1515
|
+
|
|
1516
|
+
# Run agent to fix issues
|
|
1517
|
+
context = self.state_manager.load_context()
|
|
1518
|
+
coding_style = self.state_manager.load_coding_style()
|
|
1519
|
+
|
|
1520
|
+
current_branch = self._get_current_branch()
|
|
1521
|
+
self.agent.run_work_session(
|
|
1522
|
+
task_description=task_description,
|
|
1523
|
+
context=context,
|
|
1524
|
+
model_override=ModelType.OPUS,
|
|
1525
|
+
required_branch=current_branch,
|
|
1526
|
+
coding_style=coding_style,
|
|
1527
|
+
)
|
|
1528
|
+
|
|
1529
|
+
state.session_count += 1
|
|
1530
|
+
self.state_manager.save_state(state)
|
|
1531
|
+
return True
|
|
1532
|
+
|
|
1533
|
+
except Exception as e:
|
|
1534
|
+
console.error(f"Failed to fix CI issues: {e}")
|
|
1427
1535
|
return False
|
|
@@ -55,9 +55,15 @@ class Planner:
|
|
|
55
55
|
# Load any existing context
|
|
56
56
|
context = self.state_manager.load_context()
|
|
57
57
|
|
|
58
|
-
#
|
|
58
|
+
# Get max_prs from state options (if state exists)
|
|
59
|
+
max_prs = None
|
|
60
|
+
if self.state_manager.state_file.exists():
|
|
61
|
+
state = self.state_manager.load_state()
|
|
62
|
+
max_prs = state.options.max_prs
|
|
63
|
+
|
|
64
|
+
# Run planning phase with Claude (with coding style and max_prs)
|
|
59
65
|
result = self.agent.run_planning_phase(
|
|
60
|
-
goal=goal, context=context, coding_style=coding_style
|
|
66
|
+
goal=goal, context=context, coding_style=coding_style, max_prs=max_prs
|
|
61
67
|
)
|
|
62
68
|
|
|
63
69
|
# Extract plan and criteria from result
|
|
@@ -10,7 +10,10 @@ from .prompts_base import PromptBuilder
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def build_planning_prompt(
|
|
13
|
-
goal: str,
|
|
13
|
+
goal: str,
|
|
14
|
+
context: str | None = None,
|
|
15
|
+
coding_style: str | None = None,
|
|
16
|
+
max_prs: int | None = None,
|
|
14
17
|
) -> str:
|
|
15
18
|
"""Build the planning phase prompt.
|
|
16
19
|
|
|
@@ -18,6 +21,7 @@ def build_planning_prompt(
|
|
|
18
21
|
goal: The user's goal to achieve.
|
|
19
22
|
context: Optional accumulated context from previous sessions.
|
|
20
23
|
coding_style: Optional coding style guide to inject.
|
|
24
|
+
max_prs: Optional maximum number of PRs to create.
|
|
21
25
|
|
|
22
26
|
Returns:
|
|
23
27
|
Complete planning prompt.
|
|
@@ -175,6 +179,28 @@ executed in a continuous conversation, so Claude remembers previous work.
|
|
|
175
179
|
**Each PR should be mergeable independently when possible.**""",
|
|
176
180
|
)
|
|
177
181
|
|
|
182
|
+
# PR limit constraint (if specified)
|
|
183
|
+
if max_prs:
|
|
184
|
+
builder.add_section(
|
|
185
|
+
"⚠️ PR LIMIT CONSTRAINT (MANDATORY)",
|
|
186
|
+
f"""**CRITICAL: You MUST create EXACTLY {max_prs} pull request(s) or fewer. This is MANDATORY.**
|
|
187
|
+
|
|
188
|
+
🚫 **YOU ARE NOT ALLOWED TO EXCEED {max_prs} PR(s). NO EXCEPTIONS.**
|
|
189
|
+
|
|
190
|
+
Everything MUST fit within {max_prs} PR(s). Plan accordingly:
|
|
191
|
+
|
|
192
|
+
{"**For 1 PR: Put EVERYTHING in a single pull request.**" if max_prs == 1 else f"**For {max_prs} PRs: Intelligently group all work into {max_prs} or fewer pull requests.**"}
|
|
193
|
+
|
|
194
|
+
- Combine ALL related changes together
|
|
195
|
+
- Group tests, docs, and code in the same PR
|
|
196
|
+
- Keep dependencies together (schema + model + service in one PR)
|
|
197
|
+
- Prioritize essential work if needed
|
|
198
|
+
|
|
199
|
+
**DO NOT CREATE MORE THAN {max_prs} PR(s) under any circumstances.**
|
|
200
|
+
|
|
201
|
+
Any plan that exceeds {max_prs} PR(s) is INVALID and will be REJECTED.""",
|
|
202
|
+
)
|
|
203
|
+
|
|
178
204
|
# Success criteria
|
|
179
205
|
builder.add_section(
|
|
180
206
|
"Step 3: Define Success Criteria",
|
claude_task_master/core/state.py
CHANGED
|
@@ -146,6 +146,18 @@ class FileOperationsMixin:
|
|
|
146
146
|
return coding_style_file.read_text()
|
|
147
147
|
return None
|
|
148
148
|
|
|
149
|
+
def delete_coding_style(self) -> bool:
|
|
150
|
+
"""Delete coding style guide file (coding-style.md).
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
True if file was deleted, False if file did not exist.
|
|
154
|
+
"""
|
|
155
|
+
coding_style_file = self.state_dir / "coding-style.md"
|
|
156
|
+
if coding_style_file.exists():
|
|
157
|
+
coding_style_file.unlink()
|
|
158
|
+
return True
|
|
159
|
+
return False
|
|
160
|
+
|
|
149
161
|
def _parse_plan_tasks(self, plan: str) -> list[str]:
|
|
150
162
|
"""Parse tasks from plan markdown.
|
|
151
163
|
|
claude_task_master/mcp/server.py
CHANGED
|
@@ -69,6 +69,7 @@ ClearMailboxResult = tools.ClearMailboxResult
|
|
|
69
69
|
CloneRepoResult = tools.CloneRepoResult
|
|
70
70
|
SetupRepoResult = tools.SetupRepoResult
|
|
71
71
|
PlanRepoResult = tools.PlanRepoResult
|
|
72
|
+
DeleteCodingStyleResult = tools.DeleteCodingStyleResult
|
|
72
73
|
|
|
73
74
|
|
|
74
75
|
# =============================================================================
|
|
@@ -201,12 +202,31 @@ def create_server(
|
|
|
201
202
|
"""
|
|
202
203
|
return tools.clean_task(work_dir, force, state_dir)
|
|
203
204
|
|
|
205
|
+
@mcp.tool()
|
|
206
|
+
def delete_coding_style(
|
|
207
|
+
state_dir: str | None = None,
|
|
208
|
+
) -> dict[str, Any]:
|
|
209
|
+
"""Delete the coding style guide file (coding-style.md).
|
|
210
|
+
|
|
211
|
+
The coding style file is a cached guide that's preserved across runs to save
|
|
212
|
+
tokens. Call this to force regeneration on the next planning phase when
|
|
213
|
+
project conventions have changed.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
state_dir: Optional custom state directory path.
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
Dictionary indicating success or failure with deletion status.
|
|
220
|
+
"""
|
|
221
|
+
return tools.delete_coding_style(work_dir, state_dir)
|
|
222
|
+
|
|
204
223
|
@mcp.tool()
|
|
205
224
|
def initialize_task(
|
|
206
225
|
goal: str,
|
|
207
226
|
model: str = "opus",
|
|
208
227
|
auto_merge: bool = True,
|
|
209
228
|
max_sessions: int | None = None,
|
|
229
|
+
max_prs: int | None = None,
|
|
210
230
|
pause_on_pr: bool = False,
|
|
211
231
|
state_dir: str | None = None,
|
|
212
232
|
) -> dict[str, Any]:
|
|
@@ -220,6 +240,7 @@ def create_server(
|
|
|
220
240
|
model: Model to use (opus, sonnet, haiku).
|
|
221
241
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
222
242
|
max_sessions: Max work sessions before pausing.
|
|
243
|
+
max_prs: Max pull requests to create.
|
|
223
244
|
pause_on_pr: Pause after creating PR for manual review.
|
|
224
245
|
state_dir: Optional custom state directory path.
|
|
225
246
|
|
|
@@ -227,7 +248,7 @@ def create_server(
|
|
|
227
248
|
Dictionary indicating success with run_id or failure.
|
|
228
249
|
"""
|
|
229
250
|
return tools.initialize_task(
|
|
230
|
-
work_dir, goal, model, auto_merge, max_sessions, pause_on_pr, state_dir
|
|
251
|
+
work_dir, goal, model, auto_merge, max_sessions, max_prs, pause_on_pr, state_dir
|
|
231
252
|
)
|
|
232
253
|
|
|
233
254
|
@mcp.tool()
|
|
@@ -317,6 +338,7 @@ def create_server(
|
|
|
317
338
|
def update_config(
|
|
318
339
|
auto_merge: bool | None = None,
|
|
319
340
|
max_sessions: int | None = None,
|
|
341
|
+
max_prs: int | None = None,
|
|
320
342
|
pause_on_pr: bool | None = None,
|
|
321
343
|
enable_checkpointing: bool | None = None,
|
|
322
344
|
log_level: str | None = None,
|
|
@@ -332,6 +354,7 @@ def create_server(
|
|
|
332
354
|
Args:
|
|
333
355
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
334
356
|
max_sessions: Maximum number of work sessions before pausing.
|
|
357
|
+
max_prs: Maximum number of pull requests to create.
|
|
335
358
|
pause_on_pr: Whether to pause after creating PR for manual review.
|
|
336
359
|
enable_checkpointing: Whether to enable state checkpointing.
|
|
337
360
|
log_level: Log level (quiet, normal, verbose).
|
|
@@ -346,6 +369,7 @@ def create_server(
|
|
|
346
369
|
work_dir,
|
|
347
370
|
auto_merge=auto_merge,
|
|
348
371
|
max_sessions=max_sessions,
|
|
372
|
+
max_prs=max_prs,
|
|
349
373
|
pause_on_pr=pause_on_pr,
|
|
350
374
|
enable_checkpointing=enable_checkpointing,
|
|
351
375
|
log_level=log_level,
|
claude_task_master/mcp/tools.py
CHANGED
|
@@ -183,6 +183,15 @@ class PlanRepoResult(BaseModel):
|
|
|
183
183
|
error: str | None = None
|
|
184
184
|
|
|
185
185
|
|
|
186
|
+
class DeleteCodingStyleResult(BaseModel):
|
|
187
|
+
"""Result from delete_coding_style tool."""
|
|
188
|
+
|
|
189
|
+
success: bool
|
|
190
|
+
message: str
|
|
191
|
+
deleted: bool = False
|
|
192
|
+
error: str | None = None
|
|
193
|
+
|
|
194
|
+
|
|
186
195
|
# =============================================================================
|
|
187
196
|
# Tool Implementations
|
|
188
197
|
# =============================================================================
|
|
@@ -402,6 +411,57 @@ def get_context(
|
|
|
402
411
|
}
|
|
403
412
|
|
|
404
413
|
|
|
414
|
+
def delete_coding_style(
|
|
415
|
+
work_dir: Path,
|
|
416
|
+
state_dir: str | None = None,
|
|
417
|
+
) -> dict[str, Any]:
|
|
418
|
+
"""Delete the coding style guide file (coding-style.md).
|
|
419
|
+
|
|
420
|
+
The coding style file is a cached guide that's preserved across runs to save
|
|
421
|
+
tokens. Call this to force regeneration on the next planning phase when
|
|
422
|
+
project conventions have changed.
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
work_dir: Working directory for the server.
|
|
426
|
+
state_dir: Optional custom state directory path.
|
|
427
|
+
|
|
428
|
+
Returns:
|
|
429
|
+
Dictionary indicating success or failure with deletion status.
|
|
430
|
+
"""
|
|
431
|
+
state_path = Path(state_dir) if state_dir else work_dir / ".claude-task-master"
|
|
432
|
+
state_manager = StateManager(state_dir=state_path)
|
|
433
|
+
|
|
434
|
+
if not state_manager.exists():
|
|
435
|
+
return DeleteCodingStyleResult(
|
|
436
|
+
success=False,
|
|
437
|
+
message="No task state found",
|
|
438
|
+
deleted=False,
|
|
439
|
+
error="No active task found. Initialize a task first.",
|
|
440
|
+
).model_dump()
|
|
441
|
+
|
|
442
|
+
try:
|
|
443
|
+
deleted = state_manager.delete_coding_style()
|
|
444
|
+
if deleted:
|
|
445
|
+
return DeleteCodingStyleResult(
|
|
446
|
+
success=True,
|
|
447
|
+
message="Coding style guide deleted successfully",
|
|
448
|
+
deleted=True,
|
|
449
|
+
).model_dump()
|
|
450
|
+
else:
|
|
451
|
+
return DeleteCodingStyleResult(
|
|
452
|
+
success=True,
|
|
453
|
+
message="Coding style guide did not exist",
|
|
454
|
+
deleted=False,
|
|
455
|
+
).model_dump()
|
|
456
|
+
except Exception as e:
|
|
457
|
+
return DeleteCodingStyleResult(
|
|
458
|
+
success=False,
|
|
459
|
+
message=f"Failed to delete coding style guide: {e}",
|
|
460
|
+
deleted=False,
|
|
461
|
+
error=str(e),
|
|
462
|
+
).model_dump()
|
|
463
|
+
|
|
464
|
+
|
|
405
465
|
def clean_task(
|
|
406
466
|
work_dir: Path,
|
|
407
467
|
force: bool = False,
|
|
@@ -464,6 +524,7 @@ def initialize_task(
|
|
|
464
524
|
model: str = "opus",
|
|
465
525
|
auto_merge: bool = True,
|
|
466
526
|
max_sessions: int | None = None,
|
|
527
|
+
max_prs: int | None = None,
|
|
467
528
|
pause_on_pr: bool = False,
|
|
468
529
|
state_dir: str | None = None,
|
|
469
530
|
) -> dict[str, Any]:
|
|
@@ -475,6 +536,7 @@ def initialize_task(
|
|
|
475
536
|
model: Model to use (opus, sonnet, haiku).
|
|
476
537
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
477
538
|
max_sessions: Max work sessions before pausing.
|
|
539
|
+
max_prs: Max pull requests to create.
|
|
478
540
|
pause_on_pr: Pause after creating PR for manual review.
|
|
479
541
|
state_dir: Optional custom state directory path.
|
|
480
542
|
|
|
@@ -494,6 +556,7 @@ def initialize_task(
|
|
|
494
556
|
options = TaskOptions(
|
|
495
557
|
auto_merge=auto_merge,
|
|
496
558
|
max_sessions=max_sessions,
|
|
559
|
+
max_prs=max_prs,
|
|
497
560
|
pause_on_pr=pause_on_pr,
|
|
498
561
|
)
|
|
499
562
|
state = state_manager.initialize(goal=goal, model=model, options=options)
|
|
@@ -772,6 +835,7 @@ def update_config(
|
|
|
772
835
|
work_dir: Path,
|
|
773
836
|
auto_merge: bool | None = None,
|
|
774
837
|
max_sessions: int | None = None,
|
|
838
|
+
max_prs: int | None = None,
|
|
775
839
|
pause_on_pr: bool | None = None,
|
|
776
840
|
enable_checkpointing: bool | None = None,
|
|
777
841
|
log_level: str | None = None,
|
|
@@ -788,6 +852,7 @@ def update_config(
|
|
|
788
852
|
work_dir: Working directory for the server.
|
|
789
853
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
790
854
|
max_sessions: Maximum number of work sessions before pausing.
|
|
855
|
+
max_prs: Maximum number of pull requests to create.
|
|
791
856
|
pause_on_pr: Whether to pause after creating PR for manual review.
|
|
792
857
|
enable_checkpointing: Whether to enable state checkpointing.
|
|
793
858
|
log_level: Log level (quiet, normal, verbose).
|
|
@@ -808,6 +873,8 @@ def update_config(
|
|
|
808
873
|
kwargs["auto_merge"] = auto_merge
|
|
809
874
|
if max_sessions is not None:
|
|
810
875
|
kwargs["max_sessions"] = max_sessions
|
|
876
|
+
if max_prs is not None:
|
|
877
|
+
kwargs["max_prs"] = max_prs
|
|
811
878
|
if pause_on_pr is not None:
|
|
812
879
|
kwargs["pause_on_pr"] = pause_on_pr
|
|
813
880
|
if enable_checkpointing is not None:
|
|
@@ -44,7 +44,7 @@ from __future__ import annotations
|
|
|
44
44
|
import uuid
|
|
45
45
|
from dataclasses import dataclass, field
|
|
46
46
|
from datetime import UTC, datetime
|
|
47
|
-
from enum import
|
|
47
|
+
from enum import StrEnum
|
|
48
48
|
from typing import Any
|
|
49
49
|
|
|
50
50
|
# =============================================================================
|
|
@@ -52,7 +52,7 @@ from typing import Any
|
|
|
52
52
|
# =============================================================================
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
class EventType(
|
|
55
|
+
class EventType(StrEnum):
|
|
56
56
|
"""Webhook event types.
|
|
57
57
|
|
|
58
58
|
Each event type corresponds to a specific lifecycle event in the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-task-master
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.10
|
|
4
4
|
Summary: Autonomous task orchestration system that keeps Claude working until a goal is achieved
|
|
5
5
|
Author: Claude Task Master Team
|
|
6
6
|
License-Expression: MIT
|
|
@@ -19,15 +19,15 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
19
19
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
20
|
Requires-Python: >=3.12
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
|
-
Requires-Dist: claude-agent-sdk>=0.1.
|
|
22
|
+
Requires-Dist: claude-agent-sdk>=0.1.30
|
|
23
23
|
Requires-Dist: typer>=0.12.0
|
|
24
24
|
Requires-Dist: pydantic>=2.0.0
|
|
25
|
-
Requires-Dist: rich>=
|
|
25
|
+
Requires-Dist: rich>=14.3.2
|
|
26
26
|
Requires-Dist: httpx>=0.27.0
|
|
27
27
|
Provides-Extra: mcp
|
|
28
|
-
Requires-Dist: mcp>=1.
|
|
28
|
+
Requires-Dist: mcp>=1.26.0; extra == "mcp"
|
|
29
29
|
Provides-Extra: api
|
|
30
|
-
Requires-Dist: fastapi>=0.
|
|
30
|
+
Requires-Dist: fastapi>=0.128.1; extra == "api"
|
|
31
31
|
Requires-Dist: uvicorn[standard]>=0.24.0; extra == "api"
|
|
32
32
|
Requires-Dist: passlib[bcrypt]>=1.7.4; extra == "api"
|
|
33
33
|
Requires-Dist: bcrypt<4.1.0,>=4.0.0; extra == "api"
|
|
@@ -37,8 +37,8 @@ Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
|
37
37
|
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
38
38
|
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
39
39
|
Requires-Dist: pytest-timeout>=2.4.0; extra == "dev"
|
|
40
|
-
Requires-Dist: hypothesis>=6.
|
|
41
|
-
Requires-Dist: ruff>=0.
|
|
40
|
+
Requires-Dist: hypothesis>=6.151.5; extra == "dev"
|
|
41
|
+
Requires-Dist: ruff>=0.15.0; extra == "dev"
|
|
42
42
|
Requires-Dist: mypy>=1.9.0; extra == "dev"
|
|
43
43
|
Provides-Extra: all
|
|
44
44
|
Requires-Dist: claude-task-master[api,dev,mcp]; extra == "all"
|
|
@@ -390,6 +390,7 @@ claudetm start "Your goal here" [OPTIONS]
|
|
|
390
390
|
| `--model` | Model to use (sonnet, opus, haiku) | sonnet |
|
|
391
391
|
| `--auto-merge/--no-auto-merge` | Auto-merge PRs when ready | True |
|
|
392
392
|
| `--max-sessions` | Limit number of sessions | unlimited |
|
|
393
|
+
| `--prs` | Limit number of PRs to create | unlimited |
|
|
393
394
|
| `--pause-on-pr` | Pause after creating PR | False |
|
|
394
395
|
|
|
395
396
|
### Common Workflows
|
|
@@ -404,6 +405,10 @@ claudetm start "Refactor auth system" --model opus --no-auto-merge
|
|
|
404
405
|
# Limited sessions to prevent runaway
|
|
405
406
|
claudetm start "Fix bug in parser" --max-sessions 5
|
|
406
407
|
|
|
408
|
+
# Limit number of PRs (forces everything into fewer PRs)
|
|
409
|
+
claudetm start "Add user dashboard" --prs 1
|
|
410
|
+
claudetm start "Implement notifications" --prs 3 --max-sessions 10
|
|
411
|
+
|
|
407
412
|
# Monitor progress
|
|
408
413
|
watch -n 5 'claudetm status'
|
|
409
414
|
|
|
@@ -435,6 +440,10 @@ claudetm start "Add dark mode toggle to settings" --model opus
|
|
|
435
440
|
# Refactoring
|
|
436
441
|
claudetm start "Refactor API client to use async/await" --max-sessions 5
|
|
437
442
|
|
|
443
|
+
# Limit PRs for focused changes
|
|
444
|
+
claudetm start "Add user authentication" --prs 1
|
|
445
|
+
claudetm start "Build admin dashboard" --prs 2 --max-sessions 8
|
|
446
|
+
|
|
438
447
|
# Documentation
|
|
439
448
|
claudetm start "Add API documentation and examples"
|
|
440
449
|
```
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
claude_task_master/__init__.py,sha256=
|
|
1
|
+
claude_task_master/__init__.py,sha256=FM8X1pOP-O8f-7DZXsRpUbBJ3ztwsqBsi9AEGfwlLSI,188
|
|
2
2
|
claude_task_master/cli.py,sha256=b2nowi18sFSX8pLZiFKjQqDp7cvRWRnNayN96n-d770,6238
|
|
3
3
|
claude_task_master/server.py,sha256=a39yqwj2gZWpAPOzU9E3yj8ds7wmSqevOyiI7QHu_EQ,15791
|
|
4
4
|
claude_task_master/wrapper.py,sha256=NQywkv06-4jkBz4lFPkQvDrr8TEMgyAqYWEnQI2fgck,6001
|
|
5
5
|
claude_task_master/api/__init__.py,sha256=PLYnsz8ce5JbMhkE3s268l898QZjR-hCiaqb97o0W0Y,2205
|
|
6
|
-
claude_task_master/api/models.py,sha256=
|
|
7
|
-
claude_task_master/api/routes.py,sha256=
|
|
6
|
+
claude_task_master/api/models.py,sha256=T8C1C2zJyxFp1y2wsG3KBrpOb6e5UrbkaV7Qgg-BHxY,27130
|
|
7
|
+
claude_task_master/api/routes.py,sha256=aC-tjlTa_4TesRcRimnKLy0u2COVk-h9fVgHh3Mfmbo,50279
|
|
8
8
|
claude_task_master/api/routes_config.py,sha256=gmLb40bxiNwF4N8U7_MarXRFnzzJWGjqQGDF4wOMjiI,5125
|
|
9
9
|
claude_task_master/api/routes_control.py,sha256=HaM6JfTTlwnfaHADXlk-Pc3FpdBWp6yzG3NBXqdfFTU,9814
|
|
10
10
|
claude_task_master/api/routes_repo.py,sha256=Lh9c1JqyBTUiuq_8Nlyig-wtVyl6Ha9rVk_20MOxCqg,11649
|
|
@@ -23,13 +23,13 @@ claude_task_master/cli_commands/fix_session.py,sha256=yXijoqCKZ9kE2_TPIwSTScTeAo
|
|
|
23
23
|
claude_task_master/cli_commands/github.py,sha256=x8UcAqBRdGUau0frkzkoeOmZ5xaN4AFUDWybFHVDXa0,5142
|
|
24
24
|
claude_task_master/cli_commands/info.py,sha256=jmzslLMiVk3ZyGBsVxNSfoe1qLJsuCG9Zqz57zYauRE,6084
|
|
25
25
|
claude_task_master/cli_commands/mailbox.py,sha256=SJzZxzxpkIv4cwXA-8gaVzqTJuqh1rwxQ4TeL-VmDE4,9291
|
|
26
|
-
claude_task_master/cli_commands/workflow.py,sha256=
|
|
26
|
+
claude_task_master/cli_commands/workflow.py,sha256=mcFOG2_4r-o0GMvhIO9GQC7_z8RPCxytd8C0jTiYMr8,17270
|
|
27
27
|
claude_task_master/core/__init__.py,sha256=nmwC07VqpbuogTYbXTYhb0KJifwsrF922FepWEHnpyc,8945
|
|
28
|
-
claude_task_master/core/agent.py,sha256=
|
|
28
|
+
claude_task_master/core/agent.py,sha256=snQmeZx4xvREuuIv-L3IlN6V7kZC0FH1BSqH41ckXVs,12064
|
|
29
29
|
claude_task_master/core/agent_exceptions.py,sha256=TjPlGXQhGjWof1kENyRmBowRNRay4SXL0YCH_VYsq4g,6354
|
|
30
|
-
claude_task_master/core/agent_message.py,sha256
|
|
30
|
+
claude_task_master/core/agent_message.py,sha256=gelItCmxluOHwiNzBQhJ-skNzFVxCVDe_qBmr6MnYao,7809
|
|
31
31
|
claude_task_master/core/agent_models.py,sha256=06kTenpOHKDFt8tOqa9h5-4fvjkwNxm2MDC3FzbbmoQ,6551
|
|
32
|
-
claude_task_master/core/agent_phases.py,sha256=
|
|
32
|
+
claude_task_master/core/agent_phases.py,sha256=XfXPLDcOeSthIm-v0uZNmgW-7gfueNnIGqqh_7-aMzA,13380
|
|
33
33
|
claude_task_master/core/agent_query.py,sha256=lu6-X3AdNC4t-THZf6Qc2lBIpwhmm7bhgWqezSbOOGY,17269
|
|
34
34
|
claude_task_master/core/checkpoint.py,sha256=qwW_Qj1yjNNuyBZEAj91bOGhn1yCsjqOccGn3XFIPRg,7142
|
|
35
35
|
claude_task_master/core/circuit_breaker.py,sha256=kXVgLDVy5_kie65frVPkrcPMmm6FWSHOqwfTe7Isebk,13545
|
|
@@ -43,25 +43,25 @@ claude_task_master/core/credentials.py,sha256=khav4RO-N5R7lG7E1VGdDztEgB1yOzYBJL
|
|
|
43
43
|
claude_task_master/core/hooks.py,sha256=ZQLsELwrCDgxmjRQfsNO8e3Tswpig-8yWZjEAjbpT98,14304
|
|
44
44
|
claude_task_master/core/key_listener.py,sha256=d-TZvEkmhYudzLkJx6SWYFBMyJMYcscZ9k9vrAXMBU0,5434
|
|
45
45
|
claude_task_master/core/logger.py,sha256=87m45KxDH3UO8JG9TFZVsstd5bpFspNVG6L5gg8fgLc,8061
|
|
46
|
-
claude_task_master/core/orchestrator.py,sha256=
|
|
46
|
+
claude_task_master/core/orchestrator.py,sha256=tNq2vJoItYiV0VmUy3Jl-wqVNdL8wAGv4205Z_OJ4FI,58210
|
|
47
47
|
claude_task_master/core/parallel.py,sha256=1eQWU4yVJCQktsK1sC98eMk42Y8OOneQXSeZ-G4psO8,14838
|
|
48
48
|
claude_task_master/core/plan_updater.py,sha256=hhLR3L9cPqDUAjxaVMPWDDwm6GFHe3xrDbAXFSFeRxA,6843
|
|
49
|
-
claude_task_master/core/planner.py,sha256=
|
|
49
|
+
claude_task_master/core/planner.py,sha256=fIEwBrKEU_uXmuJOqL6_NLj1V786oa4nb_5B9pDgveM,3176
|
|
50
50
|
claude_task_master/core/pr_context.py,sha256=C1kxyona1LUTFcag-CHp86T-YJYTunPlJEAGllqBUTE,19534
|
|
51
51
|
claude_task_master/core/progress_tracker.py,sha256=nQS4LKjQcy0ptNJFH80nBAz_ygbVbgn73ItdBbe6tzk,12068
|
|
52
52
|
claude_task_master/core/prompts.py,sha256=WPPQQGYvUq_vF4muKuBuYoB8fq3hU1E6lZhDSB34-V8,2212
|
|
53
53
|
claude_task_master/core/prompts_base.py,sha256=pCJsHWq1hxoLC_f5c_GwaaXFdwIkyIseU9qmtZwVt3c,1981
|
|
54
54
|
claude_task_master/core/prompts_coding_style.py,sha256=kGmd8Sq0-nTnNLS8qrqSwxv3Adk6bRNZ0C1Uq1jGzpA,4756
|
|
55
55
|
claude_task_master/core/prompts_plan_update.py,sha256=Gvq1urZ3Cn6IMGDN6XQosKb0GjbLxKYeCVBbP-SREpY,4314
|
|
56
|
-
claude_task_master/core/prompts_planning.py,sha256=
|
|
56
|
+
claude_task_master/core/prompts_planning.py,sha256=kAjh5LVYH5Ee-YOkKUEP0D7itmJ_nFLl5nf6RsUp1Ts,8280
|
|
57
57
|
claude_task_master/core/prompts_verification.py,sha256=h4fW8hF479BA0I43BWNLzDGHcGqn86Dh_xfXpSvmeEE,4624
|
|
58
58
|
claude_task_master/core/prompts_working.py,sha256=HsCmVJFnn71HAcbkSR4J8A5UOsMfL4jUB-SqCEPRma4,11449
|
|
59
59
|
claude_task_master/core/rate_limit.py,sha256=r_ztFybFHTP1UWJIW66OTqAUNJLffyCo7uPwrpFUO1c,4439
|
|
60
60
|
claude_task_master/core/shutdown.py,sha256=-WaP6FoAgvdBGOmu6AtEu9YWA4n0v8AP9Cm_39g_BW8,10194
|
|
61
|
-
claude_task_master/core/state.py,sha256=
|
|
61
|
+
claude_task_master/core/state.py,sha256=LzXGGBZhOBBiJ8GhUdBg04z39KLE__busBVuY0W2d1A,24842
|
|
62
62
|
claude_task_master/core/state_backup.py,sha256=OJnFotGNyCxzDBbfmtd8zo8VyEHVvsxGH_NRBNL0Ma8,5780
|
|
63
63
|
claude_task_master/core/state_exceptions.py,sha256=7nJ5-tBf-owTU68a07pkdUq-DnUV_D7DbNMuNSzsVLc,6691
|
|
64
|
-
claude_task_master/core/state_file_ops.py,sha256=
|
|
64
|
+
claude_task_master/core/state_file_ops.py,sha256=91nRGA1vf-vHNHDJdvypH2uCXdhngHP45Yv5clbp-PQ,5423
|
|
65
65
|
claude_task_master/core/state_pr.py,sha256=R8pwmzP15yStFji_Epq1p8VcWdLN96aG8mAcndi5p1U,7926
|
|
66
66
|
claude_task_master/core/state_recovery.py,sha256=1kIOd_dnRF3ZbjNohTXDzanBsfAhrWcQUNzGdg3rN9o,3812
|
|
67
67
|
claude_task_master/core/subagents.py,sha256=-O4dsywG2-FWwB6kg20GwaVIuQ2DAWcrkJYIBvmVM1Q,6759
|
|
@@ -80,17 +80,17 @@ claude_task_master/mailbox/models.py,sha256=CTLqm3M2Mvw_cZQSaphGE1x05fFFTQMOHzh1
|
|
|
80
80
|
claude_task_master/mailbox/storage.py,sha256=n0gzVp64R12pMtX1TQbJuraQfzASCsD53xgeyfdVWo4,6372
|
|
81
81
|
claude_task_master/mcp/__init__.py,sha256=uLd6VkJlzO3qKaYRLTVEM5OJrGi5wlSIzNLre_tPhgw,1018
|
|
82
82
|
claude_task_master/mcp/auth.py,sha256=K1FHszG7Klnn0j1k9n0krueSmZ4Q8_gKw8NDRp0OFU4,5459
|
|
83
|
-
claude_task_master/mcp/server.py,sha256=
|
|
84
|
-
claude_task_master/mcp/tools.py,sha256=
|
|
83
|
+
claude_task_master/mcp/server.py,sha256=XE1tjmk37P2arp6QnYpo8ZT-AJW-Hr2uQwega5XJ3mY,28223
|
|
84
|
+
claude_task_master/mcp/tools.py,sha256=2QJS1FaDPeQr9WsU9q7YgViwFwEsqir94lvlMWiB7Ak,59302
|
|
85
85
|
claude_task_master/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
86
86
|
claude_task_master/utils/debug_claude_md.py,sha256=88opwpoh9ApR3ZyRVFro3e6jpngR3_kGoB5abdLA1As,6620
|
|
87
87
|
claude_task_master/utils/doctor.py,sha256=z9mm9RUVVAYuFzCWd03kjUXMvKFxXVDyeiuqS5-RXYA,2796
|
|
88
88
|
claude_task_master/webhooks/__init__.py,sha256=bJfQBkSRZCOaVNnOg7PlG-FbwJV4YsySD2st0Z4uGFk,1981
|
|
89
89
|
claude_task_master/webhooks/client.py,sha256=DEz3vrNmuTBPp2t_rK515zRRKJAzFxxL8B9iCbXRuEU,24589
|
|
90
90
|
claude_task_master/webhooks/config.py,sha256=cufVrl94zSSubpoNFWVYp5ht2Okf_K_8UAQfFsaaOIE,19230
|
|
91
|
-
claude_task_master/webhooks/events.py,sha256=
|
|
92
|
-
claude_task_master-0.1.
|
|
93
|
-
claude_task_master-0.1.
|
|
94
|
-
claude_task_master-0.1.
|
|
95
|
-
claude_task_master-0.1.
|
|
96
|
-
claude_task_master-0.1.
|
|
91
|
+
claude_task_master/webhooks/events.py,sha256=V-kWjb6QF2PpFJ3FtSP6hGP-Ivhdt2Tg71g6NXi1iwY,32141
|
|
92
|
+
claude_task_master-0.1.10.dist-info/METADATA,sha256=vjkSZyIy0Zg_nLXZXbD6CudonMWn-qjUvtHnLYQoZm0,29955
|
|
93
|
+
claude_task_master-0.1.10.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
94
|
+
claude_task_master-0.1.10.dist-info/entry_points.txt,sha256=vpjSBkvZSSZ1WmmNSbiszyiiy-fAvtmmaOTOyLnufqM,251
|
|
95
|
+
claude_task_master-0.1.10.dist-info/top_level.txt,sha256=Axj8q87a_7qo5JyjdIFe9ebs4BFOnuDt_gdxHqSDwqc,19
|
|
96
|
+
claude_task_master-0.1.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|