claude-task-master 0.1.5__py3-none-any.whl → 0.1.6__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.5"
6
+ __version__ = "0.1.6"
7
7
  __all__ = ["__version__"]
@@ -33,7 +33,7 @@ set -euo pipefail
33
33
 
34
34
  # Script version - synchronized with Python package version
35
35
  # This should be kept in sync using scripts/sync_version.py
36
- SCRIPT_VERSION="0.1.5"
36
+ SCRIPT_VERSION="0.1.6"
37
37
 
38
38
  # Configuration file location
39
39
  CONFIG_DIR=".claude-task-master"
@@ -109,8 +109,8 @@ class ToolsConfig(BaseModel):
109
109
  """
110
110
 
111
111
  planning: list[str] = Field(
112
- default_factory=lambda: ["Read", "Glob", "Grep", "Bash"],
113
- description="Tools available during planning phase (read-only + bash for checks).",
112
+ default_factory=lambda: ["Read", "Glob", "Grep", "Bash", "WebFetch", "WebSearch"],
113
+ description="Tools available during planning phase (read-only + bash for checks + web tools for research).",
114
114
  )
115
115
  verification: list[str] = Field(
116
116
  default_factory=lambda: ["Read", "Glob", "Grep", "Bash"],
@@ -152,7 +152,7 @@ class ClaudeTaskMasterConfig(BaseModel):
152
152
  "auto_push": true
153
153
  },
154
154
  "tools": {
155
- "planning": ["Read", "Glob", "Grep", "Bash"],
155
+ "planning": ["Read", "Glob", "Grep", "Bash", "WebFetch", "WebSearch"],
156
156
  "verification": ["Read", "Glob", "Grep", "Bash"],
157
157
  "working": []
158
158
  }
@@ -36,14 +36,18 @@ testing strategy, and how all pieces fit together. Plan for success.
36
36
  - `Glob` - Find files by pattern
37
37
  - `Grep` - Search for code patterns
38
38
  - `Bash` - Run commands (git status, tests, lint checks, etc.)
39
+ - `WebSearch` - Search the web for current information (use FIRST to find URLs)
40
+ - `WebFetch` - Fetch full content from URLs (only URLs from search results or user-provided)
41
+
42
+ **Web Research Workflow:** Use `WebSearch` first to find relevant documentation/articles,
43
+ then use `WebFetch` to retrieve full content from specific URLs in the search results.
44
+ WebFetch can also retrieve PDFs for technical documentation.
39
45
 
40
46
  **FORBIDDEN TOOLS (NEVER use during planning):**
41
47
  - ❌ `Write` - Do NOT write any files
42
48
  - ❌ `Edit` - Do NOT edit any files
43
49
  - ❌ `Task` - Do NOT launch any agents
44
50
  - ❌ `TodoWrite` - Do NOT use todo tracking
45
- - ❌ `WebFetch` - Do NOT fetch web pages
46
- - ❌ `WebSearch` - Do NOT search the web
47
51
 
48
52
  **WHY**: The orchestrator will save your plan to `plan.md` automatically.
49
53
  You just need to OUTPUT the plan as TEXT in your response.
@@ -157,6 +157,62 @@ class TaskRunner:
157
157
  self._parsed_groups_cache = None
158
158
  self._plan_hash = None
159
159
 
160
+ def _get_group_context(self, state: TaskState, plan: str | None = None) -> dict | None:
161
+ """Get PR group context for the current task.
162
+
163
+ Computes information about the current task's PR group including:
164
+ - Group name and ID
165
+ - Whether this is the last task in the group
166
+ - Remaining tasks in the group
167
+ - Completed tasks in the group
168
+
169
+ Args:
170
+ state: Current task state.
171
+ plan: Optional plan content. If not provided, loads from state manager.
172
+
173
+ Returns:
174
+ Dict with group context, or None if no plan or task out of range.
175
+ Keys: group_id, group_name, is_last_in_group, remaining_in_group,
176
+ completed_tasks, tasks_in_group
177
+ """
178
+ if plan is None:
179
+ plan = self.state_manager.load_plan()
180
+ if not plan:
181
+ return None
182
+
183
+ parsed_tasks, _ = self._get_parsed_tasks(plan)
184
+ if state.current_task_index >= len(parsed_tasks):
185
+ return None
186
+
187
+ current_task = parsed_tasks[state.current_task_index]
188
+ group_id = current_task.group_id
189
+ group_name = current_task.group_name
190
+
191
+ # Get all tasks in this group
192
+ tasks_in_group = [t for t in parsed_tasks if t.group_id == group_id]
193
+
194
+ # Find the current task's position within the group
195
+ current_task_in_group_idx = next(
196
+ (i for i, t in enumerate(tasks_in_group) if t.index == state.current_task_index),
197
+ 0,
198
+ )
199
+
200
+ # Calculate remaining tasks
201
+ remaining_in_group = len(tasks_in_group) - current_task_in_group_idx - 1
202
+ is_last_in_group = remaining_in_group == 0
203
+
204
+ # Get completed tasks in this group (for context)
205
+ completed_tasks = [t.cleaned_description for t in tasks_in_group if t.is_complete]
206
+
207
+ return {
208
+ "group_id": group_id,
209
+ "group_name": group_name,
210
+ "is_last_in_group": is_last_in_group,
211
+ "remaining_in_group": remaining_in_group,
212
+ "completed_tasks": completed_tasks,
213
+ "tasks_in_group": tasks_in_group,
214
+ }
215
+
160
216
  def run_work_session(self, state: TaskState) -> None:
161
217
  """Run a single work session.
162
218
 
@@ -204,25 +260,19 @@ class TaskRunner:
204
260
  complexity, cleaned_task = parse_task_complexity(current_task)
205
261
  target_model = TaskComplexity.get_model_for_complexity(complexity)
206
262
 
207
- # Get PR/group info for this task
208
- parsed_tasks, groups = self._get_parsed_tasks(plan)
209
- pr_name = "Default"
210
- pr_group_id = "default"
211
- if state.current_task_index < len(parsed_tasks):
212
- pr_name = parsed_tasks[state.current_task_index].group_name
213
- pr_group_id = parsed_tasks[state.current_task_index].group_id
214
-
215
- # Determine if this is the last task in the PR group
216
- tasks_in_group = [t for t in parsed_tasks if t.group_id == pr_group_id]
217
- current_task_in_group_idx = next(
218
- (i for i, t in enumerate(tasks_in_group) if t.index == state.current_task_index),
219
- 0,
220
- )
221
- remaining_in_group = len(tasks_in_group) - current_task_in_group_idx - 1
222
- is_last_in_group = remaining_in_group == 0
223
-
224
- # Get completed tasks in this group (for context)
225
- completed_in_group = [t.cleaned_description for t in tasks_in_group if t.is_complete]
263
+ # Get PR/group context for this task (reuses _get_group_context for DRY)
264
+ group_context = self._get_group_context(state, plan)
265
+ if group_context:
266
+ pr_name = group_context["group_name"]
267
+ is_last_in_group = group_context["is_last_in_group"]
268
+ remaining_in_group = group_context["remaining_in_group"]
269
+ completed_in_group = group_context["completed_tasks"]
270
+ else:
271
+ # Fallback for edge cases (shouldn't happen in normal operation)
272
+ pr_name = "Default"
273
+ is_last_in_group = True
274
+ remaining_in_group = 0
275
+ completed_in_group = []
226
276
 
227
277
  # Load context safely
228
278
  try:
@@ -480,19 +530,8 @@ Please complete this task."""
480
530
  Returns:
481
531
  True if this is the last task in the PR group.
482
532
  """
483
- plan = self.state_manager.load_plan()
484
- if not plan:
485
- return True
486
-
487
- parsed_tasks, _ = self._get_parsed_tasks(plan)
488
- if state.current_task_index >= len(parsed_tasks):
533
+ group_context = self._get_group_context(state)
534
+ if group_context is None:
535
+ # No plan or task out of range - treat as last task
489
536
  return True
490
-
491
- current_group_id = parsed_tasks[state.current_task_index].group_id
492
- tasks_in_group = [t for t in parsed_tasks if t.group_id == current_group_id]
493
- current_task_in_group_idx = next(
494
- (i for i, t in enumerate(tasks_in_group) if t.index == state.current_task_index),
495
- 0,
496
- )
497
- remaining_in_group = len(tasks_in_group) - current_task_in_group_idx - 1
498
- return remaining_in_group == 0
537
+ return bool(group_context["is_last_in_group"])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-task-master
3
- Version: 0.1.5
3
+ Version: 0.1.6
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
@@ -1,4 +1,4 @@
1
- claude_task_master/__init__.py,sha256=0urP21mDOkLBkps2S7nrEhvqws5ky_7tS1Pys3vm3AQ,187
1
+ claude_task_master/__init__.py,sha256=ql9nsfrSrBdezkb7MsnRGUvzZaF2qj3Fvq1xtkptjtI,187
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
@@ -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=RS16SkM_CX_lrV22O5A2XbtXq3ZN3hR_seHXekQOYJo,16650
16
+ claude_task_master/bin/claudetm,sha256=lnWkVHSRCTjr-mAqs_N2tdmsjb7BN5lZZGsLRWtRqpU,16650
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
@@ -33,7 +33,7 @@ claude_task_master/core/agent_phases.py,sha256=wj0D8m15jIY09duCrZU-L82ikLs3W6nQa
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=fgZHHCXcDAeJgy_7VIg2ezaQMNWaDKCOIDFfAJjcgVc,8590
36
+ claude_task_master/core/config.py,sha256=ei6M6jdSVsM66HQ9xrN2Do8-ve44mZwWC3VXEUnBzU0,8665
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
@@ -52,7 +52,7 @@ claude_task_master/core/progress_tracker.py,sha256=nQS4LKjQcy0ptNJFH80nBAz_ygbVb
52
52
  claude_task_master/core/prompts.py,sha256=V-s13DiVN7_fV83GqntCx9VqBjZq-H2GH4eiGm8b-yU,1866
53
53
  claude_task_master/core/prompts_base.py,sha256=pCJsHWq1hxoLC_f5c_GwaaXFdwIkyIseU9qmtZwVt3c,1981
54
54
  claude_task_master/core/prompts_plan_update.py,sha256=Gvq1urZ3Cn6IMGDN6XQosKb0GjbLxKYeCVBbP-SREpY,4314
55
- claude_task_master/core/prompts_planning.py,sha256=BxWt4hls3rU9XhCiC4D_FqNhk2u9TF4U9N8dAMIk6CE,5891
55
+ claude_task_master/core/prompts_planning.py,sha256=Y9b1RRej9Iz_SWcRBLoVNOBRVlRNHjWVwOrehqmF4iM,6219
56
56
  claude_task_master/core/prompts_verification.py,sha256=h4fW8hF479BA0I43BWNLzDGHcGqn86Dh_xfXpSvmeEE,4624
57
57
  claude_task_master/core/prompts_working.py,sha256=5DnbTinlElbEYSFRCdKQ03d94FTsRRLNBOO_3cWWtyE,9050
58
58
  claude_task_master/core/rate_limit.py,sha256=r_ztFybFHTP1UWJIW66OTqAUNJLffyCo7uPwrpFUO1c,4439
@@ -65,7 +65,7 @@ claude_task_master/core/state_pr.py,sha256=R8pwmzP15yStFji_Epq1p8VcWdLN96aG8mAcn
65
65
  claude_task_master/core/state_recovery.py,sha256=1kIOd_dnRF3ZbjNohTXDzanBsfAhrWcQUNzGdg3rN9o,3812
66
66
  claude_task_master/core/subagents.py,sha256=-O4dsywG2-FWwB6kg20GwaVIuQ2DAWcrkJYIBvmVM1Q,6759
67
67
  claude_task_master/core/task_group.py,sha256=NAxx7-MZ6JTpRjlQzgbiLGCkI8K52lIVEG3TtgeS0IY,9514
68
- claude_task_master/core/task_runner.py,sha256=61DEQIJ0dkals1Ucv41TOM95oerrCRPidqBD_ExZz70,16602
68
+ claude_task_master/core/task_runner.py,sha256=jBEAQP_iQKLp4H-60XhR40cwPpgSCuiOBd56sRT4hZ4,17975
69
69
  claude_task_master/core/workflow_stages.py,sha256=k8yCFTUJROt0ACYpRF-jt68oj8_soXRyG41W2R4IlNo,33405
70
70
  claude_task_master/github/__init__.py,sha256=N3qXxFc8jL9cjDaHZCGc_hGhc4GEfUqktsDq6569790,892
71
71
  claude_task_master/github/client.py,sha256=LFRsurhRAyMXzbkYOvVOcnllzHKrKFhLBEPTOjL4JkI,8625
@@ -88,8 +88,8 @@ claude_task_master/webhooks/__init__.py,sha256=bJfQBkSRZCOaVNnOg7PlG-FbwJV4YsySD
88
88
  claude_task_master/webhooks/client.py,sha256=DEz3vrNmuTBPp2t_rK515zRRKJAzFxxL8B9iCbXRuEU,24589
89
89
  claude_task_master/webhooks/config.py,sha256=cufVrl94zSSubpoNFWVYp5ht2Okf_K_8UAQfFsaaOIE,19230
90
90
  claude_task_master/webhooks/events.py,sha256=dbzOEdrum_joa4AUizVKxyPQW6q3TVAXDft5kxlr8O8,32140
91
- claude_task_master-0.1.5.dist-info/METADATA,sha256=15XVjBOR95ZWMnZtXP166_tCkTVY7JoKyukApU9gWdc,29580
92
- claude_task_master-0.1.5.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
93
- claude_task_master-0.1.5.dist-info/entry_points.txt,sha256=vpjSBkvZSSZ1WmmNSbiszyiiy-fAvtmmaOTOyLnufqM,251
94
- claude_task_master-0.1.5.dist-info/top_level.txt,sha256=Axj8q87a_7qo5JyjdIFe9ebs4BFOnuDt_gdxHqSDwqc,19
95
- claude_task_master-0.1.5.dist-info/RECORD,,
91
+ claude_task_master-0.1.6.dist-info/METADATA,sha256=Y5hXri1C7U3wXI3ji1ib5w0MOOJHhcyzf4pHmj2l0N8,29580
92
+ claude_task_master-0.1.6.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
93
+ claude_task_master-0.1.6.dist-info/entry_points.txt,sha256=vpjSBkvZSSZ1WmmNSbiszyiiy-fAvtmmaOTOyLnufqM,251
94
+ claude_task_master-0.1.6.dist-info/top_level.txt,sha256=Axj8q87a_7qo5JyjdIFe9ebs4BFOnuDt_gdxHqSDwqc,19
95
+ claude_task_master-0.1.6.dist-info/RECORD,,