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.
@@ -3,5 +3,5 @@
3
3
  Uses Claude Agent SDK to keep Claude working until a goal is achieved.
4
4
  """
5
5
 
6
- __version__ = "0.1.8"
6
+ __version__ = "0.1.10"
7
7
  __all__ = ["__version__"]
@@ -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(str, Enum):
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(str, Enum):
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(str, Enum):
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(str, Enum):
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
@@ -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("Registered info routes: /status, /plan, /logs, /progress, /context, /health")
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(),
@@ -171,7 +171,11 @@ class AgentWrapper:
171
171
  )
172
172
 
173
173
  def run_planning_phase(
174
- self, goal: str, context: str = "", coding_style: str | None = None
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
- result_text = message.result
85
- console.newline() # Add newline after completion
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, goal: str, context: str = "", coding_style: str | None = None
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
- # Poll CI until success or failure
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
- break
1455
+ return "success"
1392
1456
  elif pr_status.ci_state in ("FAILURE", "ERROR"):
1393
- console.error("Fix PR CI failed - cannot auto-merge")
1394
- return False
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 False
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 False
1467
+ return "interrupted"
1404
1468
  waited += poll_interval
1405
1469
 
1406
- if waited >= max_wait:
1407
- console.warning("Timed out waiting for fix PR CI")
1408
- return False
1470
+ console.warning("Timed out waiting for fix PR CI")
1471
+ return "interrupted"
1409
1472
 
1410
- # Merge the PR
1411
- if state.options.auto_merge:
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
- # Checkout back to target branch
1418
- self._checkout_to_main()
1476
+ Saves CI failure logs and runs an agent to fix the issues.
1419
1477
 
1420
- return True
1421
- except Exception as e:
1422
- console.error(f"Failed to merge fix PR: {e}")
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
- else:
1425
- console.info(f"Fix PR #{pr_number} ready to merge (auto_merge disabled)")
1426
- console.detail("Merge manually then run 'claudetm resume'")
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
- # Run planning phase with Claude (with coding style)
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, context: str | None = None, coding_style: str | None = None
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",
@@ -78,6 +78,7 @@ class TaskOptions(BaseModel):
78
78
 
79
79
  auto_merge: bool = True
80
80
  max_sessions: int | None = None
81
+ max_prs: int | None = None
81
82
  pause_on_pr: bool = False
82
83
  enable_checkpointing: bool = False
83
84
  log_level: str = "normal" # quiet, normal, verbose
@@ -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
 
@@ -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,
@@ -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 Enum
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(str, Enum):
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.8
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.0
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>=13.0.0
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.0.0; extra == "mcp"
28
+ Requires-Dist: mcp>=1.26.0; extra == "mcp"
29
29
  Provides-Extra: api
30
- Requires-Dist: fastapi>=0.100.0; extra == "api"
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.100.0; extra == "dev"
41
- Requires-Dist: ruff>=0.3.0; extra == "dev"
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=JAKhI_GFk5m5HASlCbJF5c_zSYuMV_GZYjOLrzWU-Lo,187
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=w5UirlQXirF94a3HCfCic2pz223PYaw2-KTVBG8cFC4,25922
7
- claude_task_master/api/routes.py,sha256=iwMREBGW37hxlmABsdzzjc8kWtSPyHA0N5Y66GrAIKk,47780
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=_ITtxFoH6JWd8vPPjdKXjmRj3RiOay3kUEwSZl7rJhA,16980
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=fRx7NzOZMsqfRFcue5Tvlq8nvkyiv5i_vP06J_awC2I,11931
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=-GYlZe0A8WCoEtuM4LHtymA4DEJLaHgpbQghpMl4i6g,6860
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=QVhPu9RJGYceoOb1yJyXsUJSNBYjLdFkJAaRHgZ6-ZM,13227
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=pSL-Uw7klHxHgHMmpG1eTRPOeZLtvJoxxYtHHXwOibE,54313
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=wYHTO6oOBE9JMFumyciw0qqbc6nTutpEt5SVqQ3_SRU,2917
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=BoA-ix8ZpXTjDFaSdxK3Nmjqq6SxPrdsN7oNuErQmJo,7275
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=wCoFubgFyW5Lj1gqum7Kz_2_khynWv7lTxtw92NxCSk,24811
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=uQ4lRPzVWWD5VhXnZhDQacJyqefK0V_38uBpQiV7zaI,5035
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=zxiaEDqijo-k2O-QuRgEkjb-hoX8Xvd1NyWku5wQS5Y,27318
84
- claude_task_master/mcp/tools.py,sha256=74f6Z7JHyqgVLlb-AkNS4b5jIaU4JhvIXmSDO14NYBo,57158
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=dbzOEdrum_joa4AUizVKxyPQW6q3TVAXDft5kxlr8O8,32140
92
- claude_task_master-0.1.8.dist-info/METADATA,sha256=w6ZU44zJZ6uVA5ZNYeOT2rXbLd3PSj9wWhZkGQ9_MBI,29580
93
- claude_task_master-0.1.8.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
94
- claude_task_master-0.1.8.dist-info/entry_points.txt,sha256=vpjSBkvZSSZ1WmmNSbiszyiiy-fAvtmmaOTOyLnufqM,251
95
- claude_task_master-0.1.8.dist-info/top_level.txt,sha256=Axj8q87a_7qo5JyjdIFe9ebs4BFOnuDt_gdxHqSDwqc,19
96
- claude_task_master-0.1.8.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.10.1)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5