--- name: task-coordination description: > DSH 跨任务协调(task_* 工具)的总控操作手册。当需要创建/查找/监督其他顶层会话任务、 自动拆分并行派发工作、派发前弹窗确认、等待任务完成、向运行中的任务纠偏或交接、 或者用户提到"总控/协调多个任务/派一个任务去做/拆成几个会话"时使用。 用户口中的"/task 插件""task 插件""task-coordinator""dsh-plugin-task-coordinator" "分发/派发子任务会话""开几个会话并行"同样指本技能的能力。 涵盖十一个 task_* 工具的投递语义、拆分决策、编排模式、命名规则、递归治理与安全边界。 whenToUse: > 协调两个以上顶层会话任务时;用户要求并行处理多项工作并汇总时;需要自动分析任务该拆成几个 会话并向用户确认拆分方案时;需要监督一个长任务的进度并纠偏或取消时;需要把上下文交接给 另一个任务时。 --- # 跨任务协调操作手册(task_* 工具) 你可以通过十一个 `task_*` 工具指挥其他顶层会话("任务")。这些消息在目标会话的 transcript 中**可见**,来源标记为 `coordinator`。 ## 工具速览 | 工具 | 用途 | |------|------| | `task_list` | 查找任务,取 sessionId;可按 `team` 过滤、可含子代理(默认不含);`ungrouped: true`(0.19.0)只列**不属于任何工作区**的会话(未分组桶的补救视图)——配合 `task_workspace` attach/migrate 归置,注册表 `expectedWorkspace` 记着调用方当时的期望目录 | | `task_progress` | 深入读一个任务:状态、队列中的消息、对话尾部、todos、goal | | `task_send` | 投递可见的后续提示词(`mode: queue` 或 `steer`),可用 `reference` 关联先前指令。**消歧(0918 实战教训)**:task_spawn 会话的汇报/通信一律用 task_send;宿主自带 `send_message` 仅限 subagent 树子代理,对登记父子会被拒(belongs to another parent),被拒后更不得在总结里误称 task_send | | `task_spawn` | 新建任务 + 命名 + 开场提示词,立即出现在会话列表;可用 `team` 编组;默认带回报约定(`reportBack`);**工作区落位兜底链**(0.19.0,默认 `ancestor` 档):显式/继承 cwd 与工作区路径精确匹配(大小写/分隔符/尾分隔符/`.` 段归一)→ 挂该工作区;cwd 在某工作区**目录树内** → 挂**最近祖先**工作区、会话工作目录归一为工作区根(回执 `placement:'ancestor-normalized'`,kickoff 会告知任务目标目录、要求文件/git 操作用显式路径);git worktree(`.git` 为文件)→ **刻意保持未分组**保隔离、回执给强警告;其余未命中 → 未分组 + 警告(`task_workspace` 补救)。回执必带 `workspace`({id,title} 或 null)与 `placement`;可选 `provider`+`model`(+`reasoningEffort`)指定子会话模型(0.13.0)——开场前安装、第一轮即生效,无效路线创建前即拒(注意:宿主语义会同步更新应用级默认模型);省略 provider+model 时回退插件默认路线(设置 → 任务编排,0.18.0),再回退宿主默认 | | `task_confirm` | **派发前确认**:把拆分方案做成审批卡弹给用户,阻塞直到回答;批准返回 `confirmationId`(默认单次;`reusable: true` 铸**任务级复用凭证**——长线任务首次分析后确认一次即可,后续各里程碑批量复用同一凭证) | | `task_confirm_select` | **多选确认/部分派发**:任务清单渲染为多选卡(中性样式,非琥珀审批卡),用户勾选要派发哪些;批准返回 `selected` 子集 + `confirmationId`,批量只能派发被勾选的标题(精确匹配);先在聊天里给出完整方案再调用 | | `task_spawn_batch` | **一次创建一批任务**(拆分执行步):传 `tasks: [{title?, prompt}]` + 统一 `team`(+ 必需的 `confirmationId`);默认带回报约定 | | `task_wait` | 阻塞直到任务空闲(或超时);支持多目标(`sessionIds` + `mode: all/any`) | | `task_cancel` | 取消目标的活动轮次,保留其排队消息 | | `task_workspace` | **工作区迁移**(0.12.0):`list` 列宿主工作区;`attach`/`detach` 把既有会话挂入/移出工作区(走宿主实体 API,校验会话 cwd 与工作区路径一致,不触碰会话内容)——修复历史落入「未分组」的会话;`migrate`(0.16.0)**跨工作区真迁移**:cwd 不一致 attach 挂不进时,克隆完整历史到目标工作区路径下出生的新会话并归档原会话(归档=工作区展示层标记:旧会话本体仍可读可写,对旧 id 发消息会分叉),任务改用返回的新 sessionId 继续;运行中的会话拒迁(先 `task_wait` 收口) | | `task_models` | **模型路由发现**(0.14.0):列出本部署**实际接入**的 provider/model/reasoning-effort 精确 id(宿主活体目录,GUI 选择器同源)+ 应用级默认模型 + 插件默认路线 `pluginDefault`(0.18.0)。指定子会话模型前先查这里——每个用户接入的路线不同,**永远不要猜 id** | **快速通道**:只想查询、不想消耗模型轮次时,用斜杠命令 `/tasks`(列任务)、 `/tasks team <名称>`(列编组)、`/tasks `(单任务进度)——直接在 GUI 返回, 不经过模型;需要动作(发消息/派发/等待/取消)时仍用 `task_*` 工具。 另外:每个会话头部右侧有「复制会话Id」按钮(0.8.0 客户端模块),用户需要引用某个会话的 `sessionId` 时,提示他点头部按钮复制即可,不必手抄。 ## 指令识别(用户的话对应什么能力) 用户通常不知道工具名,指令往往含糊。遇到下列说法,指的就是本技能的能力——按本手册行动, 不要忽略,也不要因为措辞不精确而拒绝执行: - 「/task 插件」「task 插件」「task-coordinator」「协调插件」→ 指本插件,即十一个 `task_*` 工具; - 「分发/派发子任务会话」「开几个会话并行做」「拆成几个会话」→ `task_spawn` / `task_spawn_batch` 扇出; - 「你作为总控会话接手」→ 按总控循环工作:分解 → `task_confirm` → `task_spawn_batch` → `task_wait` 收集 → 汇总推进,不要把所有事都自己做; - 「允许子任务启用多个子 agent」→ 把这句话原样写进每个派发项的 `prompt`(subagent 是子任务 会话自己的原生能力,不需要你代劳)。 ### 总控指令模板(含 /goal 的 objective 写法) /goal 模式每一轮都重新以 objective 文本为锚,总控意图必须**写进 objective、点名工具、用要求语气**。 推荐模板: > 作为总控会话接手接下来的开发:① 可拆分的工作必须用 task_spawn_batch 派发给子任务会话并行执行 > (附 team 名),不要全部自己做;② 用 task_wait 收集结果并汇总;③ 子任务会话内可再用 subagent > 并行;④ 完成里程碑或关键节点及时推送远端 main。 含糊授权(如「可以随时使用 /task 插件」)是可做可不做的裁量,轮次会倾向单干——避免这种写法; 若收到这种指令,主动按总控循环执行,并建议用户按模板改写目标。 ## 投递语义(关键) - 目标**空闲**:`task_send` 立即启动它的新一轮执行。 - 目标**运行中**:消息排队,在边界被消费—— - `queue`(默认):下一个**轮次**边界(当前轮做完后处理); - `steer`:下一个**步骤**边界(更快的中途纠偏)。 - **投递 ≠ 消费**:`delivered: true` 只表示消息进了收件箱。超时、异常或长时间无响应时, 先用 `task_progress` 看队列和对话尾部**对账**(消息是否已被消费、任务是否已按它行动), 再决定补发还是继续等——**绝不把不确定的投递当新消息盲发**。 - **每轮恰好消费 1 条 next-turn**:新轮首步消化队首 1 条(同一步顺带吸收全部 next-step 积压)——排队深度 N ≈ 本条 N 轮后才被读(目标运行中先等当前轮结束;中途出错会中断连续消化,剩余滞留待下一条消息唤醒)。`task_send` 回执的 `queueDepth.nextTurn`(投递后口径,含本条)就是这个 N。 - **steer 跳队但有代价**(目标健康运行中):步边界消费 steer 时完全不碰 next-turn 队列——先于整个队列生效;代价是回合不收尾(next-step 非空就不结束),连发多条同批合并、通常只多延一步。目标空闲或 abort 收尾期,steer 降级为 next-turn 排队(不跳队)。 - **冷会话即返**:`task_wait` 对无 live agent 的冷目标立即返回 already-idle——冷 ≠ 无待办(持久化队列可能还在,且 `maxQueuePerTask` 深度守卫不覆盖冷目标)。 - 结论:不需要轮询。投递后 `task_wait` 等空闲,再 `task_progress` 读结果。 ## 三级中断阶梯 按打断强度递增: | 级 | 工具 | 何时生效 | 跳队 | 代价 | |---|---|---|---|---| | 1 | `task_send` queue | 空闲→立即开新轮;运行中→当前轮结束后新轮首步(FIFO,每轮恰好 1 条,同批顺带吸收全部 next-step 积压) | 否,排队尾 | 无 | | 2 | `task_send` steer | 健康运行中→下一步边界;空闲/abort 收尾期→降级为 next-turn 排队 | 是(运行中):先于整个 next-turn 队列;降级后不跳 | 延长当前回合:next-step 非空就不收尾,连发多条同批合并、通常只多延一步 | | 3 | `task_cancel` | 请求立即停止(断 LLM 流、停启新调用;已启动的工具调用等其自然收尾);排队消息保留 | 是(相对当前轮):提前了轮边界,但终止后不自动消费——需下一条消息唤醒 | 在跑工作作废(transcript 留痕) | 判据一句话:**晚一步 = 白干一步 → 插队**。消息会改变目标正在进行的下一步(叫停/方向变更/纠偏/冲突预警)用 steer;只改变未来某轮上下文(放行确认、补充背景、非紧急交接)用 queue。steer 与 cancel 之间:steer 改方向,cancel 推倒重来——且 cancel 后目标需下一条消息才被唤醒。 反模式: - ❌ 连发多条 steer 指望叠加打断——同一步边界合并成一批,通常只延长一步; - ❌ 给空闲**且队空**的目标 steer(与 queue 等价,白付复杂度;若 next-turn 队列非空,steer 是插队工具); - ❌ 给深度 N 的目标 queue 一条"下一步就作废"的急迫纠偏——N 轮后才被读。 - 硬地板:单个超长工具调用(如全量测试电池)内部没有步边界——steer 也进不去,只剩第 3 级。 ## 关联与追溯 - `task_send` 返回 `messageId`,`task_spawn` 返回 `correlationId`——记下需要被引用的那一条。 - 纠偏/续接先前指令时,给 `task_send` 传 `reference: `, 引用会以可见注释行随消息送达,目标任务能明确知道"这是对哪条指令的修正"。 ## 拆分决策(拆成几个任务、什么时候不拆) 收到多项工作先做**拆分分析**,再动手派发: 1. **枚举子工作**:把任务分解到"一个会话能独立完成"的粒度。 2. **三维独立性判据**(全满足才可并行): - **文件/模块不重叠**:两个子项不改同一批文件(否则合并冲突); - **无数据依赖**:A 的产出不是 B 的输入; - **验证可独立**:各自能独立验证完成。 3. **拆分数量**:N 个独立工作面 → N 个任务,一一对应;不为了"看起来并行"而拆。 4. **何时不拆**(直接自己做或用单个任务): - 单文件/小范围修改;强耦合的串行链路(上游产出是下游输入); - 子项小到"协调开销 > 自己做完";探索性任务方向未定(先单个任务探路,明确了再拆)。 5. **执行**:先 `task_confirm({ plan })` 把方案做成审批卡给用户——**批量派发(≥2 个任务)前必须先确认**; 批准后拿到 `confirmationId`,再 `task_spawn_batch({ tasks, team, confirmationId })` 一次批量创建 (默认上限 6 个/批,`maxBatchSpawn`),统一 `team`;随后 `task_wait({ sessionIds, mode: 'all' })` 收口。 6. **确认语义**: - 批准 → 按方案派发(`confirmationId` 单次使用,绑定你的会话); - 用户选了「暂不派发」(确认卡文案跟随宿主语言设置;英文界面为 "Not now")或写了意见 → **不派发**,把反馈并入修订方案后重新确认; - 用户关闭卡片(`confirm-cancelled`)→ 停止,等用户下一条消息,不重试弹窗; - 无 UI 连接(`no-question-channel`)→ 降级:把方案用普通文字发给用户,在聊天里取得同意再派发。 7. **为什么必须确认**:拆分是静默决策的重灾区——弹窗强制把"拆成几个、每个干什么、为什么这样拆" 摆到用户面前,作答前无法派发,问答落转录可审计。 ## 编排模式 ### 1. 扇出—等待—汇总(并行派发) ``` 分析拆分 → 弹窗确认: task_confirm({ plan: 拆分方案全文 }) 批准后批量创建: task_spawn_batch({ tasks: [{title, prompt}, ...], team: '本次工作流名', confirmationId }) 一次等待全部: task_wait({ sessionIds: [...], mode: 'all' }) 对每个子任务: task_progress({ sessionId }) 读最终输出 汇总成一份结果 ``` - spawn 的 prompt 必须自包含(子任务看不到你的上下文):写清目标、约束、期望的输出形式。 - 给同批任务同一个 `team`:之后 `task_list({ team })` 随时找回整组,宿主重启后依然有效。 - 需要"任何一个先完成就先处理"时用 `mode: 'any'`。 **结果汇报**:派发的任务默认带回报约定(`reportBack`,spawn 时自动写进开场词)——子任务完成后 会主动 `task_send` 结果摘要(结论、产出路径、遗留问题)回你的会话。所以: - 收到子任务的汇报消息 → 记录结果,不必再读它的转录; - `task_wait` 仍是兜底:等到空闲而没收到汇报,用 `task_progress` 读; - 确实不需要汇报的一次性任务(自己会去读转录的)传 `reportBack: false`。 ### 2. 监督—纠偏 ``` task_progress 看进度 → 发现跑偏 → 任务运行中: task_send(mode: 'steer', message: 纠偏指令) 任务已空闲: task_send(mode: 'queue', message: 纠偏指令) → task_wait → task_progress 确认纠正生效 ``` ### 3. 取消与恢复 `task_cancel` 只停当前轮次,排队消息保留、会话仍可用;之后可继续 `task_send` 让它按新指令重来。完全作废一个任务时:取消 + 不再发消息即可(无删除工具)。 ### 4. 交接 向一个已完成的任务发送带完整上下文的后续指令(`task_send`),它带着自己的历史继续工作; 比新建任务更省上下文,适合迭代同一主题。 ### 5. 部分派发(多选确认,0.10.0) ``` 聊天里给出完整拆分方案 → task_confirm_select({ tasks: [{title, scope}…] }) ← 用户勾选要派发的子集(可写调整意见) → 批准: { selected, confirmationId } → task_spawn_batch 只发被勾选的标题(精确匹配, 夹带未勾选标题会报 confirmation-mismatch) → 未勾选任何项: 视为调整意见,修订清单后再确认 ``` 适用:任务之间可独立取舍、用户可能只想先做一部分。整批"全要/全不要"的审批用 `task_confirm`(计划全文审批卡);两种凭证都是绑定调用方的。 **长线任务(goal 模式)只确认一次**:首次分析出总体路线图后,用 `task_confirm({ plan, reusable: true })` 铸任务级复用凭证;此后同一使命的每个 `task_spawn_batch` 都带这同一个 `confirmationId`,不再逐里程碑弹卡。单次凭证 (默认)仍是"一批一卡"。 ### 6. 让位—唤醒(goal 模式事件循环) goal 模式的自动连续轮与回合让位天然互补:**结束回合 ≠ 停工**。把每一轮当作一个事件节拍:开头消费排队的子任务报告 → 决策/评审 → 派发或纠偏 → 尽快结束回合。 - 排队报告在下一轮开头自动送达(每轮 1 条)——这就是你的唤醒信号,不需要在回合内等它; - 监督 ≠ 亲自下场:验证电池(pytest/vitest 等)派给子任务或写进子任务自验步骤,总控回合内只做只读对账(`task_progress`)与决策; - `task_wait` 是有界兜底(默认 120s、上限 600s),不是常驻等待:无事可做就结束回合,goal 连续轮与排队消息会唤醒你; - 本模式限 goal 模式(或确知有外部消息会唤醒你);普通会话照旧用 `task_wait` 收口。 ### 7. 阶段评审门(多阶段子任务) 多阶段任务在 spawn prompt 里二选一写明跑法,不要留给子任务默认连跑: - **连续跑**(吞吐优先):阶段间无决策点、方向已锁定;总控保留 steer 做中途纠偏——它全程不空闲,queue 消息永远到不了,只有 steer 能进。 - **阶段评审门**(控制优先):凡产出会影响后续方向的阶段,让子任务"发阶段报告 → 结束回合 → 等指示";你的回复会在它空闲时自动开新轮送达。收到阶段报告后**必须回应**(放行/调整/停止,一句话即可)——它已让位在等你,不回应它就一直挂起。 门数预算:每个门消耗你一轮 + 子任务一轮;只在评审真的可能改变走向的地方设门。 ## task_spawn 命名规则 `title` 只填语义部分 **`类型|主题`**: - 类型 ∈ {功能、设计、修复、优化、发布、探索、文档、研究};英文别名(fix/feature/design/optimize/release/explore/docs/research 及常见变体)自动归一到中文规范集(自定义类型集按精确或大小写不敏感匹配);拿不准就只填主题(兜底「探索」),不要猜; - 主题 ≤16 字、具体、适合侧栏显示,不重复项目名; - **不要自己写日期**——插件按会话创建时间(Asia/Shanghai)自动盖 `MMDD|` 前缀。 示例:`修复|对账精度` → `0904|修复|对账精度`;`功能|导出报表` → `0904|功能|导出报表`。 ## 递归治理(子任务还能再拆吗) 你派出的子任务也是顶层会话,同样拥有 `task_*` 工具和本手册——**它可以作为下一级总控继续拆分**。 但必须遵守治理规则: - **深度上限**(`maxSpawnDepth`,默认 2):根会话派出的任务记为深度 1,深度 1 任务再派记为 深度 2;深度 2 的任务尝试再派会被拒绝(错误码 `spawn-depth-exceeded`)。 - **被深度拒绝时**:不要绕过——改用**会话内 subagent** 做更深一层的并行(subagent 不占 任务深度、无 GUI 入口,适合纯执行的子工作)。 - **并行还是串行**: - 子项之间**无依赖** → 并行(`task_spawn_batch` + `task_wait mode: all`); - 上游产出是下游输入 → **串行交接**:`task_wait` 等上游空闲 → `task_progress` 取其产出要点 → `task_send` 把要点作为下游的输入交接(或直接把要点写进下一个 `task_spawn` 的 prompt)。 - **停止拆分**:单个子项一轮内可独立完成、或继续拆的收益小于协调开销时,就地执行。 - **选择标准**:需要 GUI 可见/可被再协调/跨重启存活 → 任务会话;纯执行、要快、不需可见性 → subagent。 ## 安全与限制 - 不能给自己发消息(会被拒绝);目标必须是顶层会话(子代理会话被栅栏隔离)。 - 同一目标限频(默认 2 秒一次)且排队深度有上限(默认 5 条;0.23.0 起设置页「任务编排」可调,0=跟随部署配置、硬上限 50,改后免重启即生效):批量派发时逐条投递即可, 被限频时稍等重试。 - 子任务默认继承你的工作目录;需要别的项目时在 `cwd` 参数里显式指定。0.19.0 起(默认 `ancestor` 档)cwd 命中工作区子树会挂最近祖先工作区并归一到工作区根——回执与 kickoff 都会明示;要保子目录 cwd 的旧行为需管理员配 `workspacePolicy: 'exact'`。 - `task_wait` 超时未空闲不代表失败:任务还在跑,可再次等待或先做别的。 ## 错误码速览 失败返回 `{ ok: false, code, error }`,按 `code` 分支而不是读文案: | code | 含义 | 建议动作 | |------|------|---------| | `self-send-denied` | 不能给自己发消息 | 改发给其他任务 | | `subagent-caller-denied` / `subagent-target-denied` | 子代理身份被栅栏拦截 | 用顶层会话协调 | | `target-not-found` | 目标不存在或已消失 | `task_list` 重新定位 | | `rate-limited` | 同一目标限频(默认 2s) | 稍等重试 | | `queue-full` | 目标排队已满(默认 5 条) | 先 `task_wait` 让它消费 | | `target-busy` | 目标正短暂忙于准入其他工作 | 稍等重试 | | `kickoff-rejected` | spawn 的会话已建但开场词被拒 | 用 `task_send` 给该会话补发指令 | | `spawn-depth-exceeded` | 超出递归深度上限(默认 2 层) | 改用 subagent 做更深层并行 | | `confirmation-required` | 批量派发缺少用户批准 | 先 `task_confirm`,拿 `confirmationId` 再派发 | | `confirmation-mismatch` | 批量夹带了多选确认未勾选的任务 | 去掉未勾选项,或重新 `task_confirm_select` | | `confirm-cancelled` | 用户关闭了确认卡片 | 停止派发,等用户下一条消息 | | `no-question-channel` | 无 UI 连接,弹不了窗 | 降级为聊天文字确认 | | `delegated-caller` | 子代理不能发起人工确认 | 把方案和待决事项写进最终结果交回上层 | | `batch-all-failed` | 批量派发全部失败 | 看 `results` 里每项的 code 分别处理 | | `workspace-not-found` | task_workspace 的目标工作区不存在/不可用 | 先 `action: list` 核对 id 或精确路径 | | `workspace-op-failed` | 宿主实体拒绝挂载(常见:会话 cwd 与工作区路径不一致) | 看错误消息里的实际 cwd;不一致就不能挂,跨工作区改用 `migrate` | | `migrate-unavailable` | 宿主版本过老,缺迁移所需的会话快照/种子创建服务 | 该宿主只能 attach/detach;升级到含 sessionQuery.readSession + sessions.create 的版本 | | `migrate-busy` | 迁移目标正在运行,克隆只带得走已持久化日志 | 先 `task_wait` 等本轮收口再迁 | | `migrate-failed` | 克隆/挂载某步失败;错误消息会说明是否已产生孤儿克隆、原会话是否未归档 | 按消息处置:孤儿克隆可手动 attach,原会话未归档就还在 | | `model-unavailable` | 指定的模型路线被宿主目录预校验拒绝(未创建会话,无孤儿) | 错误消息附该 provider 实际可用的模型(或可路由 provider 列表);完整目录用 `task_models` | | `model-select-failed` | 会话已创建但模型安装失败(开场未发送) | 结果含孤儿 sessionId:手动选好模型后 task_send 补开场,或 task_cancel | | `catalog-unavailable` | 宿主版本过老/目录后端故障,`task_models` 拿不到目录 | 依赖 task_spawn 的 model-unavailable 错误提示纠正 id | | `target-cold` | 目标无活动代理,无可取消 | 无需处理 | ## 反模式 - ❌ 用 `task_send` 轮询进度——用 `task_progress` 读,用 `task_wait` 等。 - ❌ 给运行中的任务发 `queue` 消息期望立刻生效——需要立刻纠偏用 `steer`。 - ❌ 超时后不查状态就重发同一条消息——先 `task_progress` 对账,避免重复指令。 - ❌ 跳过 `task_confirm` 直接批量派发——会被 `confirmation-required` 拦住;确认是硬闸门不是建议。 - ❌ 用户关闭确认卡片后立刻再弹一次——停手等用户说话。 - ❌ spawn 时写一行模糊指令("帮我处理一下")——子任务没有上下文,指令必须自包含。 - ❌ 把长文档整段塞进 spawn 标题——标题只放类型和主题,内容放 prompt。 - ❌ 跨项目派发不带显式 `cwd`——子会话默认继承总控的 cwd 并挂进总控所在工作区;任务属于别的项目时,必须传与目标工作区路径精确匹配的 `cwd`(0.19.0 起传该工作区**子目录**也会挂最近祖先工作区、会话 cwd 归一为工作区根——回执 `placement:'ancestor-normalized'` 与 kickoff 提示都会明示;事后补救用 `task_workspace` 的 `migrate`)。 - ❌ 把任务派进 git worktree 还指望它自动挂主仓工作区——0.19.0 起 worktree(`.git` 为文件)被识别后**刻意保持未分组**以保隔离,回执只给强警告;确需分组用 `task_workspace migrate`(克隆以工作区根出生,worktree 隔离同样丢失,慎用)。 - ❌ 收到回执的 ungrouped 警告不处理——先看 `warning` 里的补救路径(`task_workspace` attach/migrate),再用 `task_list({ ungrouped: true })` 审计全部未分组会话、对照注册表 `expectedWorkspace` 批量归置;`team` 编组不受工作区影响,逻辑分组仍可用。 - ❌ 看到 `placement:'ancestor-normalized'` 就以为派错了——那是默认 `ancestor` 档的正常行为:会话 cwd 归一为工作区根,但 kickoff 已告知任务目标目录并要求文件/git 操作用显式路径;不要因 cwd 在根就重复派发。 - ❌ `migrate` 成功后继续对旧 id 发 `task_send`——任务已在返回的新 sessionId 下继续;旧会话只是被工作区归档标记,本体仍可读可写,对旧 id 发消息会唤醒旧副本、与新副本分叉成两条线。 - ❌ 总控马拉松回合驻留——在自己回合内自跑长验证(pytest/vitest 电池)或反复 `task_wait` 空等:子任务报告只在你自己的回合边界被消费(每轮 1 条),全部锁死在收件箱。goal 模式下结束回合即可,连续轮自动接手、排队报告下一轮开头送达。 - ❌ 收到子任务阶段报告不回应——它按约定让位等你指示;哪怕一句"放行"也要发,否则它永久挂起。 - ❌ 对全程连跑的多阶段任务发 queue 消息指望它消费——它不空闲就永远轮不到;连跑任务的中途纠偏用 steer。