- Complete tasks A6.1, A6.2, A6.3: Turn manager discussion mode handling - Complete tasks A7.1, A7.2, A7.3, A7.5: Hook-level discussion channel protections - Add closed discussion channel check to message-sent hook to prevent handoffs - Update TASKLIST.md to mark completed tasks with [x]
16 KiB
16 KiB
TASKLIST - Dirigent 开发任务拆分
A. CSM / Discussion Callback
A1. 需求与方案冻结
- 通读并确认
plans/CSM.md中的 MVP 范围、非目标和边界条件 - 确认 CSM 第一版只新增一条对外工具:
discuss-callback - 确认
discord_channel_create仅做参数扩展,不改变普通建频道行为 - 确认讨论结束后的 session 级 no-reply 覆盖继续沿用现有插件机制
- 确认
summaryPath的合法范围仅限发起讨论 Agent 的 workspace - 确认 discussion metadata 是否仅做内存态,还是需要落盘恢复
A2. 模块拆分与落点确认
- 确认
plugin/tools/register-tools.ts负责:- 扩展
discord_channel_create - 注册
discuss-callback
- 扩展
- 确认
plugin/core/下新增 discussion metadata 管理模块 - 确认
plugin/core/moderator-discord.ts继续负责 moderator 发消息能力 - 确认
plugin/turn-manager.ts仅负责 turn 状态与轮转,不直接承担业务文案拼接 - 确认 discussion 业务编排逻辑应放在新模块,而不是散落到多个 hook 中
- 确认 origin callback 与 discussion close 逻辑的调用路径
A3. plugin/tools/register-tools.ts
A3.1 扩展 discord_channel_create
- 阅读当前
discord_channel_create的参数定义与执行逻辑 - 为
discord_channel_create增加可选参数callbackChannelId - 为
discord_channel_create增加可选参数discussGuide - 添加联动校验:若传
callbackChannelId,则必须传discussGuide - 保证不传
callbackChannelId时,行为与当前版本完全一致 - 创建成功后识别是否为 discussion 模式 channel
- 在 discussion 模式下调用 metadata 初始化逻辑
- 在 discussion 模式下调用 moderator kickoff 发送逻辑
A3.2 注册 discuss-callback
- 定义
discuss-callback的 parameters schema - 注册新工具
discuss-callback - 将
discuss-callback执行逻辑接到 discussion service / manager - 为工具失败场景返回可读错误信息
A4. plugin/core/ 新增 discussion metadata/service 模块
A4.1 新建 metadata/state 模块
- 新建 discussion state 类型定义文件(如
plugin/core/discussion-state.ts) - 定义 discussion metadata 类型:
modediscussionChannelIdoriginChannelIdinitiatorAgentIdinitiatorSessionIddiscussGuidestatuscreatedAtcompletedAtsummaryPath
- 提供按
discussionChannelId查询 metadata 的方法 - 提供创建 metadata 的方法
- 提供更新状态的方法
- 提供关闭 discussion channel 的状态写入方法
A4.2 新建 discussion service 模块
- 新建 discussion service(如
plugin/core/discussion-service.ts) - 封装 discussion channel 创建后的初始化逻辑
- 封装 callback 校验逻辑
- 封装 callback 成功后的收尾逻辑
- 封装 origin channel moderator 通知逻辑
- 封装“channel 已关闭,仅做留档使用”的统一回复逻辑
A4.3 workspace 路径校验
- 新增 path 校验辅助函数
- 校验
summaryPath文件存在 - 校验
summaryPath位于 initiator workspace 下 - 防止
..、绝对路径越界、软链接绕过等路径逃逸问题
A5. plugin/core/moderator-discord.ts
- 确认当前
sendModeratorMessage(...)是否已足够支撑新流程 - 如有必要,补充统一错误日志和返回值处理
- 确认可被 discussion service 复用发送:
- kickoff message
- idle reminder
- callback 完成通知
- channel closed 固定回复
A6. plugin/turn-manager.ts
A6.1 理解现有轮转机制
- 梳理
initTurnOrder/checkTurn/onNewMessage/onSpeakerDone/advanceTurn - 确认“轮转一圈无人发言”在现有实现中的判定条件
- 确认 discussion 模式需要在哪个信号点插入“idle reminder”
A6.2 discussion 模式的空转处理
- 设计 discussion 模式下的 idle reminder 触发方式
- 确定是直接改
turn-manager.ts,还是由上层在nextSpeaker === null时识别 discussion channel - 确保 discussion channel 空转时 moderator 会提醒 initiator 收尾
- 确保普通 channel 仍保持原有 dormant 行为
A6.3 关闭后禁言
- 明确 discussion channel
closed后 turn-manager 是否还需要保留状态 - 如需要,增加对 closed discussion channel 的快速短路判断
- 避免 closed channel 再次进入正常轮转
A7. Hooks 与 session 状态
A7.1 plugin/hooks/before-model-resolve.ts
- 梳理当前 session 级 no-reply 覆盖的触发路径
- 确认如何将 closed discussion channel 相关 session 强制落到
noReplyProvider/noReplyModel - 确认该逻辑是通过 metadata 状态判断,还是通过额外 session 标记判断
- 确保该覆盖只作用于指定 discussion session,不影响其他 channel/session
- 为 closed discussion channel 的覆盖路径补充调试日志
A7.2 plugin/hooks/before-message-write.ts
- 梳理当前 NO_REPLY / end-symbol / waitIdentifier 的处理逻辑
- 找到 discussion channel 中“轮转一圈无人发言”后最适合触发 idle reminder 的位置
- 如果
nextSpeaker === null且当前 channel 是 active discussion channel:- 调用 moderator idle reminder
- 不直接让流程无提示沉默结束
- 避免重复发送 idle reminder
- closed discussion channel 下,阻止继续进入正常 handoff 流程
A7.3 plugin/hooks/message-sent.ts
- 确认该 hook 是否也会参与 turn 收尾,避免与
before-message-write.ts重复处理 - 检查 discussion channel 场景下是否需要同步补充 closed/idle 分支保护
- 确保 callback 完成后的 closed channel 不会继续触发 handoff
A7.4 plugin/hooks/message-received.ts
- 梳理 moderator bot 消息当前是否已被过滤,避免 moderator 自己再次触发讨论链路
- 对 closed discussion channel 的新消息增加统一处理入口
- 若 closed discussion channel 收到新消息:
- 不再唤醒任何 Agent 正常讨论
- 由 moderator 回复“channel 已关闭,仅做留档使用”
- 避免 moderator 的 closed 提示消息反复触发自身处理
A7.5 plugin/core/session-state.ts(如需)
- 检查现有 session 相关缓存是否适合扩展 discussion 状态
- 若需要,为 discussion session 增加专用标记缓存
- 区分:普通 no-reply 决策 vs discussion close 强制 no-reply
- 确保 session 生命周期结束后相关缓存可清理
A8. plugin/core/identity.ts / plugin/core/channel-members.ts / plugin/core/turn-bootstrap.ts
- 梳理 initiator identity 的可获取路径
- 确认 callback 时如何稳定识别 initiator account/session
- 确认 discussion channel 创建后 turn order 是否需立即 bootstrap
- 确认 discussion participant 的成员集合获取方式是否可直接复用现有逻辑
A9. plugin/index.ts
- 注入新增 discussion metadata/service 模块依赖
- 将 discussion service 传入工具注册逻辑
- 将 discussion 相关辅助能力传入需要的 hooks
- 保持插件初始化结构清晰,避免在
index.ts中堆业务细节
A10. moderator 消息模板整理
A10.1 kickoff message
- 定稿 discussion started 模板
- 模板中包含
discussGuide - 模板中明确 initiator 结束责任
- 模板中明确
discuss-callback(summaryPath)调用要求
A10.2 idle reminder
- 定稿 discussion idle 模板
- 模板中提醒 initiator:写总结文件并 callback
- 避免提醒文案歧义或像自动总结器
A10.3 origin callback message
- 定稿发回原工作 channel 的结果通知模板
- 模板中包含
summaryPath - 模板中包含来源 discussion channel
- 模板中明确“继续基于该总结文件推进原任务”
A10.4 closed reply
- 定稿 closed channel 固定回复模板
- 明确 channel 已关闭,仅做留档使用
A11. discuss-callback 详细校验任务
- 校验当前 channel 必须是 discussion channel
- 校验当前 discussion 状态必须是
active - 校验调用者必须是 initiator
- 校验
summaryPath非空 - 校验
summaryPath文件存在 - 校验
summaryPath路径在 initiator workspace 内 - 校验 callback 未重复执行
- callback 成功后写入
completedAt - callback 成功后记录
summaryPath - callback 成功后切换 discussion 状态为
completed/closed
A12. 关闭后的行为封口
- closed discussion channel 中所有旧 session 继续使用 no-reply 覆盖
- closed discussion channel 中任何新消息都不再进入真实讨论
- closed discussion channel 的任何新消息统一走 moderator 固定回复
- 防止 closed channel 中 moderator 自己的回复再次触发回环
- 明确 archived-only 的最终行为与边界
A13. 测试与文档收尾
A13.1 工具层测试
- 测试普通
discord_channel_create不带新参数时行为不变 - 测试
discord_channel_create带callbackChannelId但缺discussGuide时失败 - 测试 discussion 模式 channel 创建成功
- 测试
discuss-callback注册成功并可调用
A13.2 metadata / service 测试
- 测试 discussion metadata 创建成功
- 测试按 channelId 查询 metadata 成功
- 测试状态流转
active -> completed/closed成功 - 测试重复 callback 被拒绝
A13.3 turn / hook 测试
- 测试 discussion channel 空转后发送 idle reminder
- 测试普通 channel 空转逻辑不受影响
- 测试 callback 成功后 discussion channel 不再 handoff
- 测试 closed discussion channel 新消息不会继续唤醒 Agent
A13.4 路径校验测试
- 测试合法
summaryPath通过 - 测试不存在文件失败
- 测试 workspace 外路径失败
- 测试
..路径逃逸失败 - 测试绝对路径越界失败
A13.5 回调链路测试
- 测试 callback 成功后 moderator 在 origin channel 发出通知
- 测试 origin channel 收到路径后能继续原工作流
- 测试 discussion channel 后续只保留留档行为
A13.6 文档交付
- 根据最终代码实现更新
plans/CSM.md - 为
discord_channel_create新增参数补文档 - 为
discuss-callback补工具说明文档 - 补 discussion metadata 与状态机说明
- 补开发/调试说明
- 输出 MVP 验收清单
B. Multi-Message Mode / Shuffle Mode
B1. 方案整理
- 通读并确认
plans/CHANNEL_MODES_AND_SHUFFLE.md - 确认 Multi-Message Mode 与 Shuffle Mode 的 MVP 范围
- 确认两项能力是否都只做 channel 级 runtime state,不立即落盘
- 明确它们与 discussion channel / waiting-for-human / dormant 的优先级关系
B2. 配置与 schema
B2.1 plugin/openclaw.plugin.json
- 增加
multiMessageStartMarker - 增加
multiMessageEndMarker - 增加
multiMessagePromptMarker - 为新增配置设置默认值:
↗️/↙️/⤵️ - 评估是否需要增加 shuffle 默认配置项
B2.2 plugin/rules.ts / config 类型
- 为 multi-message mode 相关配置补类型定义
- 为 shuffle mode 相关 channel state / config 补类型定义
- 确保运行时读取配置逻辑可访问新增字段
B3. plugin/core/ 新增 channel mode / shuffle state 模块
- 新增 channel mode state 模块(如
plugin/core/channel-modes.ts) - 定义 channel mode:
normal/multi-message - 提供
enterMultiMessageMode(channelId) - 提供
exitMultiMessageMode(channelId) - 提供
isMultiMessageMode(channelId) - 提供 shuffle 开关状态存取方法
- 评估 shuffle state 是否应并入 turn-manager 内部状态
B4. plugin/hooks/message-received.ts
B4.1 Multi-Message Mode 入口/出口
- 检测 human 消息中的 multi-message start marker
- start marker 命中时,将 channel 切换到 multi-message mode
- 检测 human 消息中的 multi-message end marker
- end marker 命中时,将 channel 退出 multi-message mode
- 避免 moderator 自己的 prompt marker 消息触发 mode 切换
B4.2 Multi-Message Mode 中的 moderator 提示
- 当 channel 处于 multi-message mode 时,人类每发一条消息触发 moderator prompt marker
- prompt marker 文案/内容使用配置项
multiMessagePromptMarker - 避免重复触发或回环
B4.3 与现有 mention override 的兼容
- 明确 multi-message mode 下 human @mention 是否忽略
- 避免 multi-message mode 与 mention override 冲突
B5. plugin/hooks/before-model-resolve.ts
- 当 channel 处于 multi-message mode 时,强制相关 session 走
noReplyProvider/noReplyModel - 确保 multi-message mode 的 no-reply 覆盖优先于普通 turn 决策
- 确保退出 multi-message mode 后恢复正常 turn 逻辑
- 补充必要调试日志
B6. plugin/turn-manager.ts
B6.1 Multi-Message Mode 与 turn pause/resume
- 设计 multi-message mode 下 turn manager 的暂停语义
- 明确 pause 是通过外层 gating,还是 turn-manager 内显式状态
- 退出 multi-message mode 后恢复 turn manager
- 退出时确定下一位 speaker 的选择逻辑
B6.2 Shuffle Mode
- 为每个 channel 增加
shuffling开关状态 - 识别“一轮最后位 speaker 发言完成”的边界点
- 在进入下一轮前执行 reshuffle
- 保证上一轮最后 speaker 不会成为新一轮第一位
- 处理单 Agent 场景
- 处理双 Agent 场景
- 处理 mention override / waiting-for-human / dormant 状态下的 reshape 边界
B7. plugin/commands/dirigent-command.ts
- 新增
/turn-shuffling子命令 - 支持:
/turn-shuffling/turn-shuffling on/turn-shuffling off
- 命令返回当前 channel 的 shuffling 状态
- 命令帮助文本补充说明
B8. plugin/index.ts
- 注入 channel mode / shuffle state 模块依赖
- 将新状态能力传给相关 hooks / turn-manager
- 保持初始化关系清晰,避免 mode 逻辑散落
B9. moderator 消息模板
- 定义 multi-message mode 下的 prompt marker 发送规则
- 明确是否需要 start / end 的 moderator 确认消息
- 定义退出 multi-message mode 后的 scheduling handoff 触发格式
B10. 测试
B10.1 Multi-Message Mode
- 测试 human 发送 start marker 后进入 multi-message mode
- 测试 multi-message mode 中 Agent 被 no-reply 覆盖
- 测试每条 human 追加消息都触发 prompt marker
- 测试 human 发送 end marker 后退出 multi-message mode
- 测试退出后 moderator 正确 handoff 给下一位 Agent
- 测试 moderator prompt marker 不会触发回环
B10.2 Shuffle Mode
- 测试
/turn-shuffling on/off生效 - 测试 shuffling 关闭时 turn order 不变
- 测试 shuffling 开启时每轮结束后会 reshuffle
- 测试上一轮最后 speaker 不会成为下一轮第一位
- 测试双 Agent 场景行为符合预期
- 测试单 Agent 场景不会异常
B10.3 兼容性测试
- 测试 multi-message mode 与 waiting-for-human 的边界
- 测试 multi-message mode 与 mention override 的边界
- 测试 shuffle mode 与 dormant 状态的边界
- 测试 shuffle mode 与 mention override 的边界
B11. 文档收尾
- 根据最终实现更新
plans/CHANNEL_MODES_AND_SHUFFLE.md - 为新增配置项补文档
- 为
/turn-shuffling补使用说明 - 输出 Multi-Message Mode / Shuffle Mode 的验收清单