Files
claude-code/docs/tools/task-management.mdx
claude-code-best c5edee431f docs: 文档检查/check 20260419 (#296)
* docs: 修复文档巡检发现的 4 处错误

- daemon.md: 反映实际实现状态(supervisor/worker 已实现而非 stub)
- bridge-mode.md: API 操作数量从 7 修正为 9
- web-search-tool.md: 文件路径从 src/tools/ 修正为 packages/builtin-tools/src/tools/
- remote-control-self-hosting.md: 补充缺失的 RCS_WS_IDLE_TIMEOUT 和 RCS_WS_KEEPALIVE_INTERVAL 配置项

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 Safety 和 Context 文档中的代码引用和类型错误

- permission-model: 修正规则来源从"五层"到八层,优先级顺序对齐代码
- permission-model: PermissionUpdate 类型改为实际的 addRules/replaceRules 等
- permission-model: 补充 acceptEdits 和 dontAsk 两种权限模式
- permission-model: DENIAL_LIMITS 字段名对齐实际代码
- plan-mode: 工具路径从 src/tools/ 改为 packages/builtin-tools/src/tools/
- compaction: 修正 COMPACTABLE_TOOLS 和 POST_COMPACT_* 的行号
- project-memory: 修正 ENTRYPOINT_NAME 常量的行号
- system-prompt: 修正 SystemPrompt 类型定义文件路径和多个行号引用

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修复 introduction 文档中的错误路径和行号引用

- why-this-whitepaper.mdx: BashTool 路径从 src/tools/ 修正为 packages/builtin-tools/src/tools/
- what-is-claude-code.mdx: 移除不存在的 Azure provider,改为实际的 7 种 provider
- architecture-overview.mdx: State 类型行号从 204 修正为 207

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修复 conversation/features 文档中的错误

- streaming.mdx: queryStreamRaw → queryModelWithStreaming 函数名修正
- streaming.mdx: Azure 提供商不存在,替换为实际 7 个提供商
- debug-mode.mdx: --inspect-wait 描述错误,实际使用 BUN_INSPECT 环境变量
- buddy.mdx: 补充缺失的 companionReact.ts、CompanionCard.tsx、index.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修复文档巡检中的源码引用错误

- feature-flags.mdx: 修正 feature() 兜底描述,实际从 bun:bundle 导入而非 cli.tsx:3 内联
- feature-flags.mdx: 修正工具 require 路径为 @claude-code-best/builtin-tools 包路径
- ant-only-world.mdx: 修正 tools.ts 中 require 路径为包路径
- ant-only-world.mdx: 修正 INTERNAL_ONLY_COMMANDS 行号 (267-295) 和数量 (24+)
- skills.mdx: 修正 COMMANDS memoize 行号 258 → 299
- mcp-protocol.mdx: 修正 fetchToolsForClient LRU 缓存上限 20 → 100
- streaming.mdx: 修正流式事件引用
- file-operations.mdx: 修正工具路径引用
- search-and-navigation.mdx: 修正搜索工具引用
- shell-execution.mdx: 修正 shell 工具引用
- buddy.mdx: 补充缺失的 frontmatter 字段
- debug-mode.mdx: 修正调试模式描述

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 tools/agent 文档中的文件路径和行号引用

- 修正 TodoWriteTool、AgentTool、ToolSearchTool 等工具路径
  src/tools/ → packages/builtin-tools/src/tools/
- 更新 Tool.ts、tools.ts、BashTool.tsx 中过时的行号引用
- 修正 WebSearchTool/WebFetchTool/EnterWorktreeTool/ExitWorktreeTool 路径
- 修正 AgentTool.tsx 中多行行号引用

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 feature 文档中的文件路径和行号引用

- ultraplan.md: 更新文件行数(525/349/127)
- fork-subagent.md: 路径迁移 src/tools/ → packages/builtin-tools/
- mcp-skills.md: 修正 getMcpSkillCommands 行号 547→604,client.ts 行号 117→129
- kairos.md: 修正 getBriefSection/getProactiveSection 行号
- proactive.md: 修正 getProactiveSection 行号 860→864

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正顶层文档中的路径迁移和行号引用

- auto-updater.md: config.ts 行号 1735→1737,标注未接入启动流程的函数
- external-dependencies.md: WebSearchTool/WebFetchTool 路径迁移到 builtin-tools 包,Vertex 行号修正
- lsp-integration.md: LSPTool 路径从 src/tools/ 迁移到 packages/builtin-tools/
- stub-recovery-design-1-4.md: 修正 Windows 绝对路径链接为标准代码引用

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 task 文档中的文件扩展名和路径引用

- task-004: AssistantSessionChooser.ts → .tsx, assistant.ts → .tsx
- task-003: cli.tsx 行号 249→272, markdownConfigLoader.ts 行号 29→35
- lan-pipes: SendMessageTool 路径迁移到 packages/builtin-tools/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 补充 computer-use-tools-reference 缺失的 Windows 工具

添加遗漏的 open_terminal 和 activate_window 两个 Windows 专属工具,
修正工具总数 37→39,Windows 工具数 10→12。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 audit/bash-classifier/token-budget/tree-sitter 文档

- feature-flags-audit: ScheduleCronTool 路径迁移、DAEMON 状态更新为 COMPLETE、assistant 文件标记已补全、UDS 标记已实现
- bash-classifier: BashPermissionRequest 文件路径修正、withRetry 行号移除
- token-budget: attachments.ts 行号范围修正
- tree-sitter-bash: bashPermissions.ts 路径迁移到 packages/builtin-tools

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 langfuse-monitoring AgentTool 路径迁移

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 bridgeApi 行号和 Tool.ts 行号引用

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 Safety/Extensibility 文档中的工具路径迁移和行号引用

- sandbox.mdx: shouldUseSandbox.ts 和 bashPermissions.ts 路径迁移至 packages/builtin-tools
- why-safety-matters.mdx: bashPermissions.ts 路径迁移(3 处)
- plan-mode.mdx: EnterPlanModeTool/prompt.ts 路径迁移
- auto-mode.mdx: Auto mode 指令行号 3464→3481
- hooks.mdx: AgentTool/runAgent.ts 路径迁移
- skills.mdx: SkillTool.ts 路径迁移
- custom-agents.mdx: Agent built-in 目录和 exploreAgent.ts 路径迁移

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 internals 文档引用计数和路径

- ant-only-world: USER_TYPE 引用计数 465→410+,工具路径迁移到 builtin-tools
- growthbook-ab-testing: growthbook.ts 行数 1156→1258
- hidden-features: 语音模式状态更新(audio-napi 已恢复)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正工具文档中的行号引用

- sub-agents: AgentTool.call 入口行号 340→387
- shell-execution: ShellCommand onTimeout 行号 129→144

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 feature 文档中的状态、路径和计数

- all-features-guide: 修正 feature flag 启用范围(dev only vs dev+build)
- tier3-stubs: 大量状态修正(stub→已实现),缩减过时条目
- workflow-scripts: 路径迁移到 builtin-tools,状态更新
- web-browser-tool: 工具状态缺失→已实现,路径迁移
- context-collapse: CtxInspectTool 状态缺失→已实现
- computer-use: 行号引用更新,平台分发描述修正
- computer-use-tools-reference: 工具数 39→38
- voice-mode: voiceModeEnabled 行数 55→54

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 更新 the-loop 查询循环行号引用

query.ts 代码变更后终止原因行号整体偏移约 40 行

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 补充 feature-flags-audit 完整 build 默认 feature 列表

添加 ULTRATHINK/LODESTONE/ACP/DAEMON 等 19 个缺失的 build 默认 feature,
修正 dev-only 特征标注(UDS_INBOX/LAN_PIPES/BG_SESSIONS/TEMPLATES)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 feature-flags-audit ConfigTool 路径迁移

ConfigTool 路径从 src/tools/ 迁移到 packages/builtin-tools/src/tools/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 feature-flags-audit BashTool 路径迁移

BashTool 路径从 src/tools/ 迁移到 packages/builtin-tools/src/tools/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 修正 feature-flags-audit SkillTool 路径迁移

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 更新 feature-flags-audit WorkflowTool 状态为已实现

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 09:30:00 +08:00

213 lines
9.1 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "任务管理系统 - TodoWrite 与 Tasks 双轨架构"
description: "揭秘 Claude Code 任务管理系统的双轨架构V1 内存 TodoWrite 与 V2 文件系统 Tasks包含依赖管理、认领竞争和验证推动机制。"
keywords: ["任务管理", "TodoWrite", "任务队列", "依赖管理", "多任务"]
---
{/* 本章目标:揭示任务系统 V1内存 TodoWrite和 V2文件系统 Task*)的双轨架构,以及依赖管理、认领竞争、验证推动的工程细节 */}
## 双轨架构TodoWrite V1 与 Tasks V2
Claude Code 的任务管理并非单一系统,而是两个并存、按运行模式切换的实现:
| 维度 | V1: TodoWrite | V2: TaskCreate / TaskUpdate / TaskList / TaskGet |
|------|--------------|--------------------------------------------------|
| **启用条件** | 非交互式pipe/SDK或 `isTodoV2Enabled()` 返回 `false` | 交互式 REPL默认或 `CLAUDE_CODE_ENABLE_TASKS=1` |
| **存储** | 内存中 `AppState.todos[sessionId]`Zustand store | 文件系统 `~/.claude/tasks/<taskListId>/<id>.json` |
| **数据模型** | `{content, status, activeForm}` — 扁平三元组 | `{id, subject, description, activeForm, owner, status, blocks[], blockedBy[], metadata}` — 完整实体 |
| **持久化** | 进程退出即丢失 | 跨进程存活,支持多 Agent 并发访问 |
| **并发安全** | 无(单会话单写者) | 文件锁 + 高水位标记 + TOCTOU 防护 |
切换逻辑位于 `isTodoV2Enabled()``src/utils/tasks.ts:133`):交互式会话默认启用 V2SDK/pipe 模式回落 V1。两者互斥——`TodoWriteTool.isEnabled` 返回 `!isTodoV2Enabled()`,而 `TaskCreateTool.isEnabled` 返回 `isTodoV2Enabled()`。
## V1TodoWrite 的极简设计
TodoWrite 本质是一个**全量替换**操作——每次调用传入完整的 `todos[]` 数组,完全覆盖之前的状态:
```typescript
// packages/builtin-tools/src/tools/TodoWriteTool/TodoWriteTool.ts — call() 核心逻辑
async call({ todos }, context) {
const todoKey = context.agentId ?? getSessionId()
const oldTodos = appState.todos[todoKey] ?? []
const allDone = todos.every(_ => _.status === 'completed')
const newTodos = allDone ? [] : todos // 全部完成则清空列表
// ... 写入 AppState
}
```
### 智能清空与验证推动
一个微妙的设计:当所有任务都 `completed` 时,`newTodos` 被设为空数组(而非保留 `completed` 列表)。这确保 UI 上不会有"已完成"的视觉噪音。
此外V1 包含一个**验证推动**verification nudge机制当主线程 Agent 完成 3+ 个任务且没有任何一个是验证步骤时,系统在 tool_result 中追加提示,催促 Agent 派生验证子 Agent
```typescript
// 条件:主线程 + 全部完成 + ≥3 项 + 无验证任务
if (allDone && todos.length >= 3 && !todos.some(t => /verif/i.test(t.content))) {
verificationNudgeNeeded = true
}
// tool_result 中追加:
// "NOTE: You just closed out 3+ tasks and none was a verification step..."
```
这是防止 Agent "自说自话地宣布完成"的防御性设计——通过结构性推动而非硬约束。
## V2文件系统持久化的任务系统
### 数据模型
每个任务是一个独立 JSON 文件,路径为 `~/.claude/tasks/<taskListId>/<id>.json`
```typescript
// src/utils/tasks.ts — TaskSchema
{
id: string, // 自增整数1, 2, 3...
subject: string, // 祈使句标题(如 "Fix auth bug"
description: string, // 详细描述
activeForm?: string, // 进行时形式(如 "Fixing auth bug"),用于 spinner
owner?: string, // 认领该任务的 Agent ID/名称
status: "pending" | "in_progress" | "completed",
blocks: string[], // 此任务阻塞哪些任务 ID
blockedBy: string[], // 哪些任务 ID 阻塞此任务
metadata?: Record<string, unknown> // 任意附加数据
}
```
### 任务列表 ID 的解析优先级
`getTaskListId()` 按 5 级优先级解析任务归属:
1. `CLAUDE_CODE_TASK_LIST_ID` 环境变量(显式覆盖)
2. 进程内 teammate 上下文的 teamName共享 leader 的任务列表)
3. `CLAUDE_CODE_TEAM_NAME` 环境变量(进程级 teammate
4. Leader 通过 `setLeaderTeamName()` 设置的 teamName
5. `getSessionId()`(独立会话的兜底)
这意味着多 Agent 团队模式下,所有 teammate 自动共享同一个任务列表,无需额外协调。
### ID 分配与高水位标记
任务 ID 是简单的递增整数,但在并发场景下需要防止竞争:
```typescript
// src/utils/tasks.ts — createTask() 简化
async function createTask(taskListId, taskData) {
release = await lockfile.lock(lockPath, LOCK_OPTIONS) // 获取排他锁
const highestId = await findHighestTaskId(taskListId) // 读取当前最大 ID
const id = String(highestId + 1) // 递增
await writeFile(path, JSON.stringify({ id, ...taskData }))
return id
}
```
锁配置使用指数退避重试 30 次(总计约 2.6 秒),适配 10+ 并发 Agent 的 swarm 场景。
高水位标记文件 `.highwatermark` 确保删除任务后 ID 不会被重用——即使任务 #5 被删除,下一个新建任务仍然是 #6。
## 依赖管理blocks / blockedBy
任务间的依赖通过双向链表式的 `blocks` / `blockedBy` 字段实现:
- `taskA.blocks = ["3"]` 表示 "任务 A 完成前,任务 3 不能开始"
- `task3.blockedBy = ["A"]` 表示 "任务 3 必须等任务 A 完成"
`blockTask()` 函数同时维护两端:
```typescript
// src/utils/tasks.ts — blockTask()
// A blocks B → 更新 A.blocks 加入 B同时更新 B.blockedBy 加入 A
if (!fromTask.blocks.includes(toTaskId)) {
await updateTask(taskListId, fromTaskId, { blocks: [...fromTask.blocks, toTaskId] })
}
if (!toTask.blockedBy.includes(fromTaskId)) {
await updateTask(taskListId, toTaskId, { blockedBy: [...toTask.blockedBy, fromTaskId] })
}
```
删除任务时,系统自动清理所有指向它的依赖引用(`deleteTask()` 遍历全部任务移除 `blocks` 和 `blockedBy` 中的引用)。
## 任务认领与并发控制
`claimTask()` 是 V2 的核心并发原语,支持两种锁定粒度:
### 1. 任务级锁(默认)
仅锁定目标任务文件,适合单 Agent 场景:
```
getTask → 检查 owner → 检查 status → 检查 blockedBy → 写入 owner
```
### 2. 列表级锁 + Agent 忙碌检查
当 `checkAgentBusy: true` 时,锁定整个任务列表目录(`.lock` 文件),原子化地完成:
```
listTasks → 检查任务状态 → 检查依赖 → 检查 Agent 是否已拥有其他未完成任务 → 写入 owner
```
认领失败有 4 种原因:
| `reason` | 含义 |
|----------|------|
| `task_not_found` | 任务 ID 不存在 |
| `already_claimed` | 已被其他 Agent 认领 |
| `already_resolved` | 任务已标记 completed |
| `blocked` | blockedBy 列表中有未完成的任务 |
| `agent_busy` | 该 Agent 已拥有其他未完成任务(仅 `checkAgentBusy` 模式) |
## Agent 团队的任务生命周期
在 swarms 模式下,任务系统的生命周期是这样的:
```
Leader 创建团队
Leader 用 TaskCreate 创建任务status=pending, owner=undefined
Leader 用 TaskUpdate 设置依赖关系addBlocks/addBlockedBy
Teammate 调用 TaskList → 发现可认领的任务
Teammate 调用 TaskUpdate(taskId, {status: "in_progress"})
→ 自动设置 owner 为 teammate 名称
→ Leader 通过 mailbox 收到 task_assignment 通知
Teammate 完成工作 → TaskUpdate(taskId, {status: "completed"})
→ tool_result 提示 "Call TaskList to find your next available task"
→ 依赖此任务的其他任务自动解锁
Teammate 异常退出 → unassignTeammateTasks()
→ 未完成任务被重置为 pending + owner=undefined
→ Leader 收到通知并重新分配
```
### Hooks 集成
TaskCreate 和 TaskUpdate 都集成了 hooks 系统:
- **创建时**`executeTaskCreatedHooks` — 外部钩子可以阻断任务创建blockingError 导致任务被立即删除)
- **完成时**`executeTaskCompletedHooks` — 外部钩子可以阻断任务标记为完成
这允许外部系统CI、审批流参与任务状态机。
## activeForm终端 UX 的细节
每个任务有两个文案字段:
- `subject`:祈使句,用于任务列表展示("Fix auth bug"
- `activeForm`:进行时形式,用于 spinner 动画("Fixing auth bug..."
当 `activeForm` 缺省时spinner 回退显示 `subject`。这个看似微小的设计确保了用户在等待时看到的是"正在做什么"而非"要做什么"。
## Plan Mode 与任务系统的配合
Plan Mode计划模式和任务系统是互补但独立的机制
1. Plan Mode 限制工具集为只读(搜索、阅读),迫使 AI 先理解再行动
2. AI 在 Plan Mode 中用 TaskCreate 建立任务列表
3. 用户审批后退出 Plan Mode
4. AI 按 `blockedBy` 拓扑序逐项执行,每项用 TaskUpdate 标记进度
`shouldDefer: true` 属性确保这些工具调用不会触发权限确认弹窗——任务管理操作始终自动批准,因为它们不产生副作用。