Files
cc-web/.planning/2026-08-11-unify-ccweb-message-reply/findings.md

5.6 KiB
Raw Blame History

发现与决策:统一 ccweb 消息回传接口

需求

  • 将 ccweb_send_message 与 ccweb_request_reply 合并为一个公开工具。
  • 使用显式参数选择单向投递或自动回传。
  • 优化工具描述、目标对话提示和来源续跑提示。
  • 保留旧调用的兼容能力,但不让新模型继续在两个公开工具间选错。
  • 本次需要实际落地并通过回归。

已确认事实

  • requestCrossConversationReply() 当前只是 sendCrossConversationMessage(..., { expectReply: true }) 的薄包装。
  • 正式 MCP 定义位于 lib/ccweb-mcp-server.js,Codex App 备用定义位于 server.js,两处描述已出现漂移。
  • ccweb_create_conversation 已经使用 requestReply 参数,现有公开 API 风格不一致。
  • buildCrossConversationRuntimeText() 当前只标注来源标题和 ID,不携带是否自动回传。
  • buildCrossConversationReplyAutoRunText() 当前只包含目标标题和返回正文,缺少 requestId、原始请求和完整性检查指令。
  • 真实会话中曾对明确要求“完成后汇报/最终验收”的任务误用 ccweb_send_message;同一会话此前使用过 ccweb_request_reply,说明问题不是工具 不可发现,而是选择语义不够强。
  • 真实会话还出现过目标返回“完成定位、准备修改”后仍继续工作的情况;提示词可降低 概率,但“turn 完成是否等于任务完成”仍是协议级风险。

并发与工作树基线

  • 当前另有两个非本对话的 running 对话:任务看板、失败插入卡片。
  • server.js、lib/ccweb-mcp-server.js、scripts/regression.js 已有未提交改动,均与本任务重叠。
  • .planning/.active_plan 指向 2026-08-11-help,.trellis/.current-task 指向 .trellis/tasks/08-11-task-board;不得覆盖。
  • 本任务使用 .planning/2026-08-11-unify-ccweb-message-reply/ 保存独立上下文。
  • 已创建 Trellis 任务 .trellis/tasks/08-11-unify-ccweb-message-reply/,但不会执行 task.py start:全局 .trellis/.current-task 正被另一个运行中对话使用。后续实施与 审查子代理必须显式读取本任务路径,不能依赖全局 current-task。

技术决策

决策 理由
replyMode 必填、无默认值 避免模型省略参数后静默失去回传
值为 one_way、return_and_continue 名称直接表达真实副作用,不暗示同步等待
公开列表移除旧工具,内部 dispatcher 保留别名 兼顾新调用清晰度与存量线程兼容
共享工具定义为单一来源 防止 MCP 与备用 dynamic tools 文案/Schema 漂移
回传模式目标提示禁止手工回复 防止同一结果重复投递或形成环路
来源续跑先判断完整性 防止把“已返回”误判成“已完成”
直接复用 CCWEB_MCP_TOOLS 生成 Codex App 备用定义 server.js 已导入正式工具清单,无需新增第三个契约模块

最新代码基线

  • server.js 顶部已导入 { TOOLS: CCWEB_MCP_TOOLS },但 codexAppCommunicationDynamicTools() 仍手写重复定义。
  • 最小单一来源方案:正式定义继续留在 lib/ccweb-mcp-server.js;该模块同时导出 reply mode 常量;server.js 从 CCWEB_MCP_TOOLS 按通信工具白名单筛选并添加 namespace: 'ccweb'。
  • 此方案同时统一所有既有通信工具描述,且不会把 task-board 工具意外加入备用列表。
  • 公开 TOOLS 不能兼作唯一调用 allowlist;需要单独的 hidden legacy name 集合,避免 已缓存 ccweb_request_reply 的旧线程在到达 dispatcher 前失败。
  • scripts/regression.js 现有 assertCcwebListConversationsScopeContract() 会从 server.js 的手写 dynamic tool 源码中截取 ccweb_list_conversations schema;改成 单一来源后该断言也必须改为调用 codexAppCommunicationTools() 并比较正式定义, 否则正确的去重实现会被旧静态断言误报。
  • 当前任务看板对话不是陈旧运行标记:其 codexapp-state.json 持续更新,正在做隔离 浏览器验收并已发现新增列 description 契约缺陷。它后续可能修改 server.js 与 scripts/regression.js,本任务必须继续等待其生产改动闭环。

待验证

  • 现有测试是否直接断言公开工具数量或旧工具名称。
  • Codex App 备用 dynamic tool 路径是否仍有实际回归覆盖。
  • 旧线程调用已不在工具列表中的旧名称时,内部 MCP dispatcher 是否仍可接收。
  • 原始请求内容加入 pending 状态是否涉及持久化格式兼容。
  • 正式 MCP 的 tools/call 是否在公开 TOOLS 之外保留隐藏旧名(必须保留)。

Trellis 规范结论

  • 仓库只声明 backend/frontend 两层;本任务属于 backend + 跨层协议,不需要加载前端组件规范。
  • backend error handling 基本为空,现有 mcpToolError 行为应作为事实规范保留。
  • backend quality 的已填内容仅针对部分 JSON 预览,与本任务无直接约束。
  • cross-layer-thinking-guide.md 要求显式定义工具 Schema → dispatcher → pending 状态 → 目标运行提示 → 来源续跑提示的完整数据流,并在入口集中校验。
  • code-reuse-thinking-guide.md 明确要求相同常量/定义单一来源;支持让 Codex App 备用工具列表直接派生自正式 MCP 定义。

资源

  • server.js:跨对话发送、回传、运行提示、dynamic tool 定义。
  • lib/ccweb-mcp-server.js:正式 MCP 工具清单与输入 Schema。
  • scripts/regression.js:跨对话 MCP 端到端回归。
  • README.md:公开工具说明。