claude-task-master 0.1.9__py3-none-any.whl → 0.1.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.
- claude_task_master/__init__.py +1 -1
- claude_task_master/api/models.py +21 -5
- claude_task_master/api/routes.py +2 -0
- claude_task_master/bin/claudetm +6 -1
- claude_task_master/cli_commands/workflow.py +8 -0
- claude_task_master/core/__init__.py +2 -0
- claude_task_master/core/agent.py +7 -2
- claude_task_master/core/agent_message.py +18 -3
- claude_task_master/core/agent_models.py +32 -5
- claude_task_master/core/agent_phases.py +7 -1
- claude_task_master/core/config.py +35 -2
- 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/mcp/server.py +6 -1
- claude_task_master/mcp/tools.py +7 -0
- claude_task_master/webhooks/events.py +2 -2
- {claude_task_master-0.1.9.dist-info → claude_task_master-0.1.11.dist-info}/METADATA +31 -8
- {claude_task_master-0.1.9.dist-info → claude_task_master-0.1.11.dist-info}/RECORD +23 -23
- {claude_task_master-0.1.9.dist-info → claude_task_master-0.1.11.dist-info}/WHEEL +0 -0
- {claude_task_master-0.1.9.dist-info → claude_task_master-0.1.11.dist-info}/entry_points.txt +0 -0
- {claude_task_master-0.1.9.dist-info → claude_task_master-0.1.11.dist-info}/top_level.txt +0 -0
claude_task_master/__init__.py
CHANGED
claude_task_master/api/models.py
CHANGED
|
@@ -48,7 +48,7 @@ Usage:
|
|
|
48
48
|
from __future__ import annotations
|
|
49
49
|
|
|
50
50
|
from datetime import datetime
|
|
51
|
-
from enum import Enum
|
|
51
|
+
from enum import Enum, StrEnum
|
|
52
52
|
from typing import Any
|
|
53
53
|
|
|
54
54
|
from pydantic import BaseModel, Field
|
|
@@ -58,7 +58,7 @@ from pydantic import BaseModel, Field
|
|
|
58
58
|
# =============================================================================
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
class TaskStatus(
|
|
61
|
+
class TaskStatus(StrEnum):
|
|
62
62
|
"""Valid task status values."""
|
|
63
63
|
|
|
64
64
|
PLANNING = "planning"
|
|
@@ -70,7 +70,7 @@ class TaskStatus(str, Enum):
|
|
|
70
70
|
FAILED = "failed"
|
|
71
71
|
|
|
72
72
|
|
|
73
|
-
class WorkflowStage(
|
|
73
|
+
class WorkflowStage(StrEnum):
|
|
74
74
|
"""Valid workflow stage values for PR lifecycle."""
|
|
75
75
|
|
|
76
76
|
WORKING = "working"
|
|
@@ -83,7 +83,7 @@ class WorkflowStage(str, Enum):
|
|
|
83
83
|
MERGED = "merged"
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
class LogLevel(
|
|
86
|
+
class LogLevel(StrEnum):
|
|
87
87
|
"""Valid log level values."""
|
|
88
88
|
|
|
89
89
|
QUIET = "quiet"
|
|
@@ -91,7 +91,7 @@ class LogLevel(str, Enum):
|
|
|
91
91
|
VERBOSE = "verbose"
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-
class LogFormat(
|
|
94
|
+
class LogFormat(StrEnum):
|
|
95
95
|
"""Valid log format values."""
|
|
96
96
|
|
|
97
97
|
TEXT = "text"
|
|
@@ -159,6 +159,7 @@ class ConfigUpdateRequest(BaseModel):
|
|
|
159
159
|
Attributes:
|
|
160
160
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
161
161
|
max_sessions: Maximum number of work sessions before pausing.
|
|
162
|
+
max_prs: Maximum number of pull requests to create.
|
|
162
163
|
pause_on_pr: Whether to pause after creating PR for manual review.
|
|
163
164
|
enable_checkpointing: Whether to enable state checkpointing.
|
|
164
165
|
log_level: Log level (quiet, normal, verbose).
|
|
@@ -176,6 +177,12 @@ class ConfigUpdateRequest(BaseModel):
|
|
|
176
177
|
le=1000,
|
|
177
178
|
description="Maximum number of work sessions before pausing",
|
|
178
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
|
+
)
|
|
179
186
|
pause_on_pr: bool | None = Field(
|
|
180
187
|
default=None,
|
|
181
188
|
description="Whether to pause after creating PR for manual review",
|
|
@@ -228,6 +235,7 @@ class TaskInitRequest(BaseModel):
|
|
|
228
235
|
model: Model to use (opus, sonnet, haiku).
|
|
229
236
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
230
237
|
max_sessions: Max work sessions before pausing.
|
|
238
|
+
max_prs: Max pull requests to create.
|
|
231
239
|
pause_on_pr: Pause after creating PR for manual review.
|
|
232
240
|
"""
|
|
233
241
|
|
|
@@ -253,6 +261,12 @@ class TaskInitRequest(BaseModel):
|
|
|
253
261
|
le=1000,
|
|
254
262
|
description="Maximum number of work sessions before pausing",
|
|
255
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
|
+
)
|
|
256
270
|
pause_on_pr: bool = Field(
|
|
257
271
|
default=False,
|
|
258
272
|
description="Pause after creating PR for manual review",
|
|
@@ -384,6 +398,7 @@ class TaskOptionsResponse(BaseModel):
|
|
|
384
398
|
Attributes:
|
|
385
399
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
386
400
|
max_sessions: Maximum number of work sessions before pausing.
|
|
401
|
+
max_prs: Maximum number of pull requests to create.
|
|
387
402
|
pause_on_pr: Whether to pause after creating PR for manual review.
|
|
388
403
|
enable_checkpointing: Whether state checkpointing is enabled.
|
|
389
404
|
log_level: Current log level.
|
|
@@ -393,6 +408,7 @@ class TaskOptionsResponse(BaseModel):
|
|
|
393
408
|
|
|
394
409
|
auto_merge: bool
|
|
395
410
|
max_sessions: int | None
|
|
411
|
+
max_prs: int | None
|
|
396
412
|
pause_on_pr: bool
|
|
397
413
|
enable_checkpointing: bool
|
|
398
414
|
log_level: str
|
claude_task_master/api/routes.py
CHANGED
|
@@ -287,6 +287,7 @@ def create_info_router() -> APIRouter:
|
|
|
287
287
|
options=TaskOptionsResponse(
|
|
288
288
|
auto_merge=state.options.auto_merge,
|
|
289
289
|
max_sessions=state.options.max_sessions,
|
|
290
|
+
max_prs=state.options.max_prs,
|
|
290
291
|
pause_on_pr=state.options.pause_on_pr,
|
|
291
292
|
enable_checkpointing=state.options.enable_checkpointing,
|
|
292
293
|
log_level=state.options.log_level,
|
|
@@ -1068,6 +1069,7 @@ def create_task_router() -> APIRouter:
|
|
|
1068
1069
|
options = TaskOptions(
|
|
1069
1070
|
auto_merge=task_init.auto_merge,
|
|
1070
1071
|
max_sessions=task_init.max_sessions,
|
|
1072
|
+
max_prs=task_init.max_prs,
|
|
1071
1073
|
pause_on_pr=task_init.pause_on_pr,
|
|
1072
1074
|
enable_checkpointing=False, # Default to False
|
|
1073
1075
|
log_level="normal", # Default to normal
|
claude_task_master/bin/claudetm
CHANGED
|
@@ -289,9 +289,14 @@ default_config = {
|
|
|
289
289
|
},
|
|
290
290
|
"models": {
|
|
291
291
|
"sonnet": "claude-sonnet-4-5-20250929",
|
|
292
|
-
"opus": "claude-opus-4-
|
|
292
|
+
"opus": "claude-opus-4-6",
|
|
293
293
|
"haiku": "claude-haiku-4-5-20251001"
|
|
294
294
|
},
|
|
295
|
+
"context_windows": {
|
|
296
|
+
"opus": 200000,
|
|
297
|
+
"sonnet": 200000,
|
|
298
|
+
"haiku": 200000
|
|
299
|
+
},
|
|
295
300
|
"git": {
|
|
296
301
|
"target_branch": "main",
|
|
297
302
|
"auto_push": True
|
|
@@ -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(),
|
|
@@ -24,6 +24,7 @@ from claude_task_master.core.agent_models import (
|
|
|
24
24
|
ModelType,
|
|
25
25
|
TaskComplexity,
|
|
26
26
|
ToolConfig,
|
|
27
|
+
get_context_window,
|
|
27
28
|
get_tools_for_phase,
|
|
28
29
|
parse_task_complexity,
|
|
29
30
|
)
|
|
@@ -246,6 +247,7 @@ __all__ = [
|
|
|
246
247
|
"MODEL_CONTEXT_WINDOWS",
|
|
247
248
|
"MODEL_CONTEXT_WINDOWS_STANDARD",
|
|
248
249
|
"DEFAULT_COMPACT_THRESHOLD_PERCENT",
|
|
250
|
+
"get_context_window",
|
|
249
251
|
# Rate limit classes
|
|
250
252
|
"RateLimitConfig",
|
|
251
253
|
# Checkpoint exceptions
|
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
|
|
|
@@ -91,12 +91,15 @@ class ToolConfig(Enum):
|
|
|
91
91
|
# Constants
|
|
92
92
|
# =============================================================================
|
|
93
93
|
|
|
94
|
-
# Model context window sizes (tokens) for auto-compact threshold calculation
|
|
95
|
-
#
|
|
96
|
-
#
|
|
94
|
+
# Model context window sizes (tokens) for auto-compact threshold calculation.
|
|
95
|
+
# These are defaults; users can override via config.json "context_windows" section.
|
|
96
|
+
# Opus 4.6 and Sonnet 4.5 support 1M context (beta, tier 4+ users).
|
|
97
|
+
# Note: The Agent SDK handles the `context-1m-2025-08-07` beta header internally.
|
|
98
|
+
# These values are only used to calculate when to trigger context compaction.
|
|
99
|
+
# See: https://platform.claude.com/docs/en/build-with-claude/context-windows
|
|
97
100
|
MODEL_CONTEXT_WINDOWS = {
|
|
98
|
-
ModelType.OPUS:
|
|
99
|
-
ModelType.SONNET: 1_000_000, # Claude Sonnet 4
|
|
101
|
+
ModelType.OPUS: 1_000_000, # Claude Opus 4.6: 1M context (beta, tier 4+)
|
|
102
|
+
ModelType.SONNET: 1_000_000, # Claude Sonnet 4.5: 1M context (beta, tier 4+)
|
|
100
103
|
ModelType.HAIKU: 200_000, # Claude Haiku 4.5: 200K context
|
|
101
104
|
}
|
|
102
105
|
|
|
@@ -107,6 +110,30 @@ MODEL_CONTEXT_WINDOWS_STANDARD = {
|
|
|
107
110
|
ModelType.HAIKU: 200_000,
|
|
108
111
|
}
|
|
109
112
|
|
|
113
|
+
|
|
114
|
+
def get_context_window(
|
|
115
|
+
model: ModelType,
|
|
116
|
+
config: ClaudeTaskMasterConfig | None = None,
|
|
117
|
+
) -> int:
|
|
118
|
+
"""Get context window size for a model, reading from config if available.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
model: The model type.
|
|
122
|
+
config: Optional config object. If None, uses hardcoded defaults.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Context window size in tokens.
|
|
126
|
+
"""
|
|
127
|
+
if config is not None:
|
|
128
|
+
context_map = {
|
|
129
|
+
ModelType.OPUS: config.context_windows.opus,
|
|
130
|
+
ModelType.SONNET: config.context_windows.sonnet,
|
|
131
|
+
ModelType.HAIKU: config.context_windows.haiku,
|
|
132
|
+
}
|
|
133
|
+
return context_map.get(model, MODEL_CONTEXT_WINDOWS[model])
|
|
134
|
+
return MODEL_CONTEXT_WINDOWS[model]
|
|
135
|
+
|
|
136
|
+
|
|
110
137
|
# Default compact threshold as percentage of context window
|
|
111
138
|
DEFAULT_COMPACT_THRESHOLD_PERCENT = 0.85 # Compact at 85% usage
|
|
112
139
|
|
|
@@ -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)
|
|
@@ -71,7 +71,7 @@ class ModelConfig(BaseModel):
|
|
|
71
71
|
description="Model name for 'sonnet' (balanced). Overridden by CLAUDETM_MODEL_SONNET.",
|
|
72
72
|
)
|
|
73
73
|
opus: str = Field(
|
|
74
|
-
default="claude-opus-4-
|
|
74
|
+
default="claude-opus-4-6",
|
|
75
75
|
description="Model name for 'opus' (smartest). Overridden by CLAUDETM_MODEL_OPUS.",
|
|
76
76
|
)
|
|
77
77
|
haiku: str = Field(
|
|
@@ -97,6 +97,30 @@ class GitConfig(BaseModel):
|
|
|
97
97
|
)
|
|
98
98
|
|
|
99
99
|
|
|
100
|
+
class ContextWindowsConfig(BaseModel):
|
|
101
|
+
"""Context window sizes per model (in tokens).
|
|
102
|
+
|
|
103
|
+
Controls the max context window size used for auto-compact threshold calculation.
|
|
104
|
+
Opus 4.6 and Sonnet 4.5 support 1M context in beta (tier 4+ users).
|
|
105
|
+
Users on lower tiers should set these to 200000.
|
|
106
|
+
|
|
107
|
+
To enable 1M context via the API, use the beta header: context-1m-2025-08-07
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
opus: int = Field(
|
|
111
|
+
default=200_000,
|
|
112
|
+
description="Opus context window size in tokens. 200000 (standard) or 1000000 (beta, tier 4+).",
|
|
113
|
+
)
|
|
114
|
+
sonnet: int = Field(
|
|
115
|
+
default=200_000,
|
|
116
|
+
description="Sonnet context window size in tokens. 200000 (standard) or 1000000 (beta, tier 4+).",
|
|
117
|
+
)
|
|
118
|
+
haiku: int = Field(
|
|
119
|
+
default=200_000,
|
|
120
|
+
description="Haiku context window size in tokens.",
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
100
124
|
class ToolsConfig(BaseModel):
|
|
101
125
|
"""Tool configurations per execution phase.
|
|
102
126
|
|
|
@@ -144,13 +168,18 @@ class ClaudeTaskMasterConfig(BaseModel):
|
|
|
144
168
|
},
|
|
145
169
|
"models": {
|
|
146
170
|
"sonnet": "claude-sonnet-4-5-20250929",
|
|
147
|
-
"opus": "claude-opus-4-
|
|
171
|
+
"opus": "claude-opus-4-6",
|
|
148
172
|
"haiku": "claude-haiku-4-5-20251001"
|
|
149
173
|
},
|
|
150
174
|
"git": {
|
|
151
175
|
"target_branch": "main",
|
|
152
176
|
"auto_push": true
|
|
153
177
|
},
|
|
178
|
+
"context_windows": {
|
|
179
|
+
"opus": 200000,
|
|
180
|
+
"sonnet": 200000,
|
|
181
|
+
"haiku": 200000
|
|
182
|
+
},
|
|
154
183
|
"tools": {
|
|
155
184
|
"planning": ["Read", "Glob", "Grep", "Bash", "WebFetch", "WebSearch"],
|
|
156
185
|
"verification": ["Read", "Glob", "Grep", "Bash"],
|
|
@@ -172,6 +201,10 @@ class ClaudeTaskMasterConfig(BaseModel):
|
|
|
172
201
|
default_factory=ModelConfig,
|
|
173
202
|
description="Model name mappings.",
|
|
174
203
|
)
|
|
204
|
+
context_windows: ContextWindowsConfig = Field(
|
|
205
|
+
default_factory=ContextWindowsConfig,
|
|
206
|
+
description="Context window sizes per model (tokens). Set to 200000 if not on tier 4+.",
|
|
207
|
+
)
|
|
175
208
|
git: GitConfig = Field(
|
|
176
209
|
default_factory=GitConfig,
|
|
177
210
|
description="Git configuration (target branch, auto-push).",
|
|
@@ -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
claude_task_master/mcp/server.py
CHANGED
|
@@ -226,6 +226,7 @@ def create_server(
|
|
|
226
226
|
model: str = "opus",
|
|
227
227
|
auto_merge: bool = True,
|
|
228
228
|
max_sessions: int | None = None,
|
|
229
|
+
max_prs: int | None = None,
|
|
229
230
|
pause_on_pr: bool = False,
|
|
230
231
|
state_dir: str | None = None,
|
|
231
232
|
) -> dict[str, Any]:
|
|
@@ -239,6 +240,7 @@ def create_server(
|
|
|
239
240
|
model: Model to use (opus, sonnet, haiku).
|
|
240
241
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
241
242
|
max_sessions: Max work sessions before pausing.
|
|
243
|
+
max_prs: Max pull requests to create.
|
|
242
244
|
pause_on_pr: Pause after creating PR for manual review.
|
|
243
245
|
state_dir: Optional custom state directory path.
|
|
244
246
|
|
|
@@ -246,7 +248,7 @@ def create_server(
|
|
|
246
248
|
Dictionary indicating success with run_id or failure.
|
|
247
249
|
"""
|
|
248
250
|
return tools.initialize_task(
|
|
249
|
-
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
|
|
250
252
|
)
|
|
251
253
|
|
|
252
254
|
@mcp.tool()
|
|
@@ -336,6 +338,7 @@ def create_server(
|
|
|
336
338
|
def update_config(
|
|
337
339
|
auto_merge: bool | None = None,
|
|
338
340
|
max_sessions: int | None = None,
|
|
341
|
+
max_prs: int | None = None,
|
|
339
342
|
pause_on_pr: bool | None = None,
|
|
340
343
|
enable_checkpointing: bool | None = None,
|
|
341
344
|
log_level: str | None = None,
|
|
@@ -351,6 +354,7 @@ def create_server(
|
|
|
351
354
|
Args:
|
|
352
355
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
353
356
|
max_sessions: Maximum number of work sessions before pausing.
|
|
357
|
+
max_prs: Maximum number of pull requests to create.
|
|
354
358
|
pause_on_pr: Whether to pause after creating PR for manual review.
|
|
355
359
|
enable_checkpointing: Whether to enable state checkpointing.
|
|
356
360
|
log_level: Log level (quiet, normal, verbose).
|
|
@@ -365,6 +369,7 @@ def create_server(
|
|
|
365
369
|
work_dir,
|
|
366
370
|
auto_merge=auto_merge,
|
|
367
371
|
max_sessions=max_sessions,
|
|
372
|
+
max_prs=max_prs,
|
|
368
373
|
pause_on_pr=pause_on_pr,
|
|
369
374
|
enable_checkpointing=enable_checkpointing,
|
|
370
375
|
log_level=log_level,
|
claude_task_master/mcp/tools.py
CHANGED
|
@@ -524,6 +524,7 @@ def initialize_task(
|
|
|
524
524
|
model: str = "opus",
|
|
525
525
|
auto_merge: bool = True,
|
|
526
526
|
max_sessions: int | None = None,
|
|
527
|
+
max_prs: int | None = None,
|
|
527
528
|
pause_on_pr: bool = False,
|
|
528
529
|
state_dir: str | None = None,
|
|
529
530
|
) -> dict[str, Any]:
|
|
@@ -535,6 +536,7 @@ def initialize_task(
|
|
|
535
536
|
model: Model to use (opus, sonnet, haiku).
|
|
536
537
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
537
538
|
max_sessions: Max work sessions before pausing.
|
|
539
|
+
max_prs: Max pull requests to create.
|
|
538
540
|
pause_on_pr: Pause after creating PR for manual review.
|
|
539
541
|
state_dir: Optional custom state directory path.
|
|
540
542
|
|
|
@@ -554,6 +556,7 @@ def initialize_task(
|
|
|
554
556
|
options = TaskOptions(
|
|
555
557
|
auto_merge=auto_merge,
|
|
556
558
|
max_sessions=max_sessions,
|
|
559
|
+
max_prs=max_prs,
|
|
557
560
|
pause_on_pr=pause_on_pr,
|
|
558
561
|
)
|
|
559
562
|
state = state_manager.initialize(goal=goal, model=model, options=options)
|
|
@@ -832,6 +835,7 @@ def update_config(
|
|
|
832
835
|
work_dir: Path,
|
|
833
836
|
auto_merge: bool | None = None,
|
|
834
837
|
max_sessions: int | None = None,
|
|
838
|
+
max_prs: int | None = None,
|
|
835
839
|
pause_on_pr: bool | None = None,
|
|
836
840
|
enable_checkpointing: bool | None = None,
|
|
837
841
|
log_level: str | None = None,
|
|
@@ -848,6 +852,7 @@ def update_config(
|
|
|
848
852
|
work_dir: Working directory for the server.
|
|
849
853
|
auto_merge: Whether to auto-merge PRs when approved.
|
|
850
854
|
max_sessions: Maximum number of work sessions before pausing.
|
|
855
|
+
max_prs: Maximum number of pull requests to create.
|
|
851
856
|
pause_on_pr: Whether to pause after creating PR for manual review.
|
|
852
857
|
enable_checkpointing: Whether to enable state checkpointing.
|
|
853
858
|
log_level: Log level (quiet, normal, verbose).
|
|
@@ -868,6 +873,8 @@ def update_config(
|
|
|
868
873
|
kwargs["auto_merge"] = auto_merge
|
|
869
874
|
if max_sessions is not None:
|
|
870
875
|
kwargs["max_sessions"] = max_sessions
|
|
876
|
+
if max_prs is not None:
|
|
877
|
+
kwargs["max_prs"] = max_prs
|
|
871
878
|
if pause_on_pr is not None:
|
|
872
879
|
kwargs["pause_on_pr"] = pause_on_pr
|
|
873
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.11
|
|
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"
|
|
@@ -295,9 +295,14 @@ This creates `.claude-task-master/config.json`:
|
|
|
295
295
|
},
|
|
296
296
|
"models": {
|
|
297
297
|
"sonnet": "claude-sonnet-4-5-20250929",
|
|
298
|
-
"opus": "claude-opus-4-
|
|
298
|
+
"opus": "claude-opus-4-6",
|
|
299
299
|
"haiku": "claude-haiku-4-5-20251001"
|
|
300
300
|
},
|
|
301
|
+
"context_windows": {
|
|
302
|
+
"opus": 200000,
|
|
303
|
+
"sonnet": 200000,
|
|
304
|
+
"haiku": 200000
|
|
305
|
+
},
|
|
301
306
|
"git": {
|
|
302
307
|
"target_branch": "main",
|
|
303
308
|
"auto_push": true
|
|
@@ -305,6 +310,15 @@ This creates `.claude-task-master/config.json`:
|
|
|
305
310
|
}
|
|
306
311
|
```
|
|
307
312
|
|
|
313
|
+
> **Note:** Opus 4.6 and Sonnet 4.5 support a 1M token context window in beta (**tier 4+** API access required). If you have tier 4+ access, you can increase the context windows:
|
|
314
|
+
> ```json
|
|
315
|
+
> "context_windows": {
|
|
316
|
+
> "opus": 1000000,
|
|
317
|
+
> "sonnet": 1000000,
|
|
318
|
+
> "haiku": 200000
|
|
319
|
+
> }
|
|
320
|
+
> ```
|
|
321
|
+
|
|
308
322
|
### Environment Variables
|
|
309
323
|
|
|
310
324
|
The config file sets these environment variables before Python starts:
|
|
@@ -390,6 +404,7 @@ claudetm start "Your goal here" [OPTIONS]
|
|
|
390
404
|
| `--model` | Model to use (sonnet, opus, haiku) | sonnet |
|
|
391
405
|
| `--auto-merge/--no-auto-merge` | Auto-merge PRs when ready | True |
|
|
392
406
|
| `--max-sessions` | Limit number of sessions | unlimited |
|
|
407
|
+
| `--prs` | Limit number of PRs to create | unlimited |
|
|
393
408
|
| `--pause-on-pr` | Pause after creating PR | False |
|
|
394
409
|
|
|
395
410
|
### Common Workflows
|
|
@@ -404,6 +419,10 @@ claudetm start "Refactor auth system" --model opus --no-auto-merge
|
|
|
404
419
|
# Limited sessions to prevent runaway
|
|
405
420
|
claudetm start "Fix bug in parser" --max-sessions 5
|
|
406
421
|
|
|
422
|
+
# Limit number of PRs (forces everything into fewer PRs)
|
|
423
|
+
claudetm start "Add user dashboard" --prs 1
|
|
424
|
+
claudetm start "Implement notifications" --prs 3 --max-sessions 10
|
|
425
|
+
|
|
407
426
|
# Monitor progress
|
|
408
427
|
watch -n 5 'claudetm status'
|
|
409
428
|
|
|
@@ -435,6 +454,10 @@ claudetm start "Add dark mode toggle to settings" --model opus
|
|
|
435
454
|
# Refactoring
|
|
436
455
|
claudetm start "Refactor API client to use async/await" --max-sessions 5
|
|
437
456
|
|
|
457
|
+
# Limit PRs for focused changes
|
|
458
|
+
claudetm start "Add user authentication" --prs 1
|
|
459
|
+
claudetm start "Build admin dashboard" --prs 2 --max-sessions 8
|
|
460
|
+
|
|
438
461
|
# Documentation
|
|
439
462
|
claudetm start "Add API documentation and examples"
|
|
440
463
|
```
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
claude_task_master/__init__.py,sha256=
|
|
1
|
+
claude_task_master/__init__.py,sha256=k1RBhhL0FsDiU9urfUvXsVWV0oWm3su8nEBp5lX5LMw,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
|
|
@@ -13,7 +13,7 @@ claude_task_master/api/server.py,sha256=xWBKKe_SMfnZuJkO9JoU-diACpd03N1SN_Sv1S0U
|
|
|
13
13
|
claude_task_master/auth/__init__.py,sha256=etobJkCGD7pUDsLArWMru4NC1fP_MLUnuCTP5htdsYU,2665
|
|
14
14
|
claude_task_master/auth/middleware.py,sha256=qeyEQHfXMtlad9bYFqJon7ScisF8JUXUSOjGFnTsx6M,14151
|
|
15
15
|
claude_task_master/auth/password.py,sha256=t4c5REJ7eD8P7gsDsKrEEJeVNF7bX017HUXGjD03_yQ,10245
|
|
16
|
-
claude_task_master/bin/claudetm,sha256=
|
|
16
|
+
claude_task_master/bin/claudetm,sha256=Ie8K20_fg0dx7cfFOU6U4NqAoTeCp4u3a0FAXip9dmU,16747
|
|
17
17
|
claude_task_master/cli_commands/__init__.py,sha256=M3m3Gx0htC5IlUVaUNTbt8nQQVKIrk1ep-pjml153G0,449
|
|
18
18
|
claude_task_master/cli_commands/ci_helpers.py,sha256=NgUu2qPmCntMQ89_yQIZ4DdW30AAroonOJt6e12aWoQ,3693
|
|
19
19
|
claude_task_master/cli_commands/config.py,sha256=iqfgP4yQvoqG5_y3UTAddxfHjD31vcRZ1hI5gOlWnvw,6462
|
|
@@ -23,17 +23,17 @@ 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=
|
|
27
|
-
claude_task_master/core/__init__.py,sha256=
|
|
28
|
-
claude_task_master/core/agent.py,sha256=
|
|
26
|
+
claude_task_master/cli_commands/workflow.py,sha256=mcFOG2_4r-o0GMvhIO9GQC7_z8RPCxytd8C0jTiYMr8,17270
|
|
27
|
+
claude_task_master/core/__init__.py,sha256=ao9bc5GLYJzsx9T2D-MqVYDx1eqk8BTvCboJ2HgZj4M,8995
|
|
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
|
|
31
|
-
claude_task_master/core/agent_models.py,sha256=
|
|
32
|
-
claude_task_master/core/agent_phases.py,sha256=
|
|
30
|
+
claude_task_master/core/agent_message.py,sha256=gelItCmxluOHwiNzBQhJ-skNzFVxCVDe_qBmr6MnYao,7809
|
|
31
|
+
claude_task_master/core/agent_models.py,sha256=PDAezIfVMb001NBg0KWImhZlnE2hk6LK6x2rFlu56kg,7560
|
|
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
|
|
36
|
-
claude_task_master/core/config.py,sha256=
|
|
36
|
+
claude_task_master/core/config.py,sha256=eXGE4tzmH81uc9z1PE-zgf5plE0t8UqwJ0MrzINvtaQ,9789
|
|
37
37
|
claude_task_master/core/config_loader.py,sha256=FWUSGKaef3DjiJPKCNL9hyJZ03RO9H9-P-9DJDOPL_c,16405
|
|
38
38
|
claude_task_master/core/console.py,sha256=GQ71zKDt0mb0bhnwkrfNxBiX4jHfFmFjNjFefTjVpiM,4208
|
|
39
39
|
claude_task_master/core/context_accumulator.py,sha256=q-T6jhX1UWHNKZ3mawXKRTUZQHxdLP88tcWtLPH_cOM,1527
|
|
@@ -43,22 +43,22 @@ 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
64
|
claude_task_master/core/state_file_ops.py,sha256=91nRGA1vf-vHNHDJdvypH2uCXdhngHP45Yv5clbp-PQ,5423
|
|
@@ -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.11.dist-info/METADATA,sha256=xmeKFvXrsfMbFKlYCyNM00TbQmlfy1ipd0FJGAUJPrU,30323
|
|
93
|
+
claude_task_master-0.1.11.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
94
|
+
claude_task_master-0.1.11.dist-info/entry_points.txt,sha256=vpjSBkvZSSZ1WmmNSbiszyiiy-fAvtmmaOTOyLnufqM,251
|
|
95
|
+
claude_task_master-0.1.11.dist-info/top_level.txt,sha256=Axj8q87a_7qo5JyjdIFe9ebs4BFOnuDt_gdxHqSDwqc,19
|
|
96
|
+
claude_task_master-0.1.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|