Files
cc-web/.planning/2026-08-11-ccweb-list-children-scope/findings.md

74 lines
7.2 KiB
Markdown
Raw 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.

# 发现与决策:ccweb_list_conversations children scope
## 需求
- 给 `ccweb_list_conversations` 增加 `scope: "children"`。
- 同步更新该 MCP 的提示词/描述。
- 完成实现、回归覆盖和验证。
## 已知代码事实
- `listConversationSummaries(args, sourceSessionId)` 当前遍历 `SESSIONS_DIR` 下全部 JSON,只按 agent/status 过滤,最后排序并应用 limit。
- MCP 创建的子会话在自身 JSON 中持久化 `createdFrom.kind = "mcp"` 和 `createdFrom.sourceSessionId`。
- `loadSessionMetaFromFile` 当前只暴露 `createdFromKind`,没有暴露来源会话 ID;实现 children 过滤需扩展元数据或读取完整会话。
- `ccweb_list_conversations` 有两处 schema/描述:`lib/ccweb-mcp-server.js` 与 `server.js` 的 Codex App 动态工具兼容定义。
- README 的 MCP 表格需要同步新语义。
- 当前工作树已有其他任务修改 `server.js`、`lib/ccweb-mcp-server.js`、`scripts/regression.js`,补丁必须基于当前内容最小追加。
- 本地 `git diff -G` 未发现既有未提交改动触碰 `ccweb_list_conversations`、`listConversationSummaries`、`loadSessionMetaFromFile` 或 `createdFromKind` 相关行;目标区域可做局部补丁。
- 当前回归先在 `scripts/regression.js` 约 6021 行测试全量列表,MCP 创建及 `createdFrom` 断言位于约 6139 行后,适合在创建完成后追加 children scope 场景。
- `createdFrom` 已包含在大文件头尾 preview 的顶层字段集合中,因此只需从现有对象提取 `sourceSessionId`,无需为 children scope 全量读取大 JSON。
- `loadSessionMetaFromFile` 的完整解析和 preview 两条分支都应新增内部字段 `createdFromSourceSessionId`;该字段只用于过滤,不必暴露到 MCP 返回摘要。
- children 过滤应紧跟 meta 读取执行,早于运行态、等待状态计算,以减少无关会话开销。
- stdio MCP 与 Codex App 兼容工具的现有描述文字不同;两者都需明确“默认全部、children 为当前来源直接 MCP 子对话”,并添加同一 enum schema。
- 两处 schema 均设置 `additionalProperties: false`,新增 `scope` 后不会影响既有 agent/status/limit 参数。
- 回归中可在首个 `mcpCreate` 完成并验证 `createdFrom` 后调用列表:此时当前来源只有一个直接 MCP 子会话,适合断言精确集合。
- 省略 scope 与显式 all 的兼容性可比较同参数调用返回的会话 ID 数组;children 应包含新建子会话且排除来源会话。
- README 当前仅有一行轻量元数据描述,可直接补充 `scope=children` 的行为与默认 all。
- 现有回归没有 branch 会话夹具;为验证 `kind === 'mcp'` 条件,需要在回归中创建一个来自同一来源的 branch,或构造等价持久会话夹具。
- 项目只有 `npm run regression` 这一完整回归入口;失败测试与最终验证均需用 `timeout 60s` 包裹。
- `handleNewSession` 创建 branch 后会把测试 WebSocket 切换到新会话;为避免干扰后续事件断言,children scope 回归应直接在临时 sessions 目录写入最小 branch/孙级夹具。
- `buildSessionInfoPayload` 虽会返回 `createdFromKind`,但 children MCP 过滤不应依赖当前 WebSocket 查看状态。
- 会话元数据完整解析阈值默认 512 KiB、preview 头尾各 128 KiB;已有 `session-preview-metadata` 定向回归以更小阈值强制走 preview 分支。
- 该定向回归已覆盖 preview 中的 `createdFrom.kind`,可扩展来源 ID 或通过内部 MCP 验证 children 过滤,避免只测试小文件路径。
- `runSessionPreviewMetadataRegression` 已配置独立内部 MCP token,可将 tail 夹具改为 `kind: mcp + sourceSessionId`,随后调用 `ccweb_list_conversations(scope=children)` 精确断言;这是最小且快速的失败回归入口。
- preview 定向回归无需真实父会话文件:列表过滤只使用自动传入的来源 ID 与子会话持久元数据比对。
- 主回归已直接导入 `lib/ccweb-mcp-server.js` 的 `TOOLS`,可对 stdio/shared MCP 的 scope enum 与描述做结构化断言。
- Codex App 当前主路径走线程级 MCP;`codexAppCommunicationDynamicTools` 是兼容定义,仍需同步文字与 schema,可用已有 server 源码审计断言或行为回归覆盖。
- 回归已有 `assertCcwebDisplayImageContract` 这类静态契约函数和 target 分派模式;可新增列表 scope 契约函数,并在 `session-preview-metadata` 定向目标及完整回归中复用。
- 完整回归后续没有对全局会话数量做精确断言,仅按 ID 查找;增加 branch 与孙级临时会话夹具不会破坏后续场景。
- 新增测试语法检查通过;实现前定向回归稳定失败在 stdio/shared MCP 缺少 scope enum,证明失败测试有效。
- 实现后 `server.js`、`lib/ccweb-mcp-server.js`、`scripts/regression.js` 语法检查全部通过,preview 定向回归通过。
- 服务端将任何非 `children` 值归一为 `all`;children 在运行态/等待态计算、排序和 limit 前完成过滤。
- 最终语法检查、session-preview-metadata 定向回归、完整 `npm run regression` 与 `git diff --check` 全部通过。
- 最终局部差异确认核心改动仅落在会话元数据、列表过滤、两处 MCP 契约、README 与回归断言;工作树中的任务看板等大段 diff 为既有改动,未被覆盖。
- 差异审查发现 preview 测试不应把原有 `ccweb_prompt_user` 夹具改写为 `mcp`;将改为新增独立大文件 MCP 子会话夹具,以保留旧覆盖。
- 已完成上述修正,定向回归、完整回归和 diff check 再次通过;没有剩余代码风险或阻塞。
- 无需重启服务即可完成代码交付;本轮未执行服务重启。
- 最终文件行号已核验,临时 CSV 已不存在,`git diff --check` 仍通过。
- 重启前运行态检查发现除当前对话外还有 2 个 running 对话;按项目运维规则暂缓 `pm2 restart ccweb --update-env`。
## 技术决策
| 决策 | 理由 |
|------|------|
| 支持 `scope: "all" | "children"` | schema 显式、可验证;默认 all 向后兼容 |
| children 匹配 `createdFrom.kind === "mcp" && createdFrom.sourceSessionId === sourceSessionId` | 精确表达直接持久子对话,不混入分支对话 |
| 非法 scope 回退 all | 正常 MCP 由 enum 约束,服务内部调用仍保持兼容与可预测 |
| 不依赖 LLM 上下文或 pending reply 状态 | 子会话持久元数据才是可重启恢复的权威来源 |
| 暂不新增返回字段 | 用户只要求过滤能力,遵循 YAGNI;现有摘要字段足以继续投递消息 |
## 风险
- 大会话文件可能走 preview 解析路径,需要确保 preview 元数据能读取 `createdFrom.sourceSessionId`。
- limit 必须在 children 过滤后应用。
- 回归测试已有大量并行任务新增内容,插入断言时避免更改无关逻辑。
- 需分别断言省略 scope、scope=all、scope=children 和非法 scope。
- 本轮 `codebase-memory-mcp` transport 已关闭;按降级策略使用本地检索,不再重复失败调用。
## 资源
- `server.js`:列表实现、会话元数据解析、Codex App 工具 schema。
- `lib/ccweb-mcp-server.js`:stdio MCP 工具 schema 与提示词。
- `scripts/regression.js`:MCP 创建及列表回归。
- `README.md`:MCP 能力说明。