Files
cc-web/.planning/subagent-card-metadata/findings.md
2026-07-18 10:14:38 +08:00

8.3 KiB
Raw Blame History

发现记录

  • 前端 collabAgentStateEntries 已读取 label/title/name 和 description/summary/message。
  • 当前渲染层仅把任务提示词和结果简介写入 DOM title,卡片正文没有显示简介。
  • 真实 Codex App spawnAgent 记录通常提供 prompt,但 agentsStates 在启动时为空,完成时 name 常为线程 ID。
  • 当前 mergeCollabAgentTools 只保留一个全局 prompt,需要把各次 spawn 的 prompt 写入对应代理状态。
  • 工作树开始时干净;已有 .planning/codex-app-worker-timeout 和根目录规划文件,不能覆盖。
  • Trellis 前端规范目前大多是模板,因此实施以现有 public/app.js / public/style.css 约定和回归测试为主要依据。
  • 原 Trellis 当前任务是 00-bootstrap-guidelines,本任务结束后需要恢复。
  • 样式集中在 public/style.css 的 .collab-agent-* 区块;需补齐 min-width: 0 / max-width: 100% 收缩链,并为新增简介采用两行 clamp。
  • 回归入口是 scripts/regression.js 的 Codex App 子代理端到端段;现有测试验证事件链但未覆盖标题/简介展示语义。
  • mock 已提供两个子代理及不同 name/role/summary,可扩展为通用名称 + 不同 prompt,验证前端合并不串任务上下文。
  • 计划复审通过;实现范围保持前端与回归测试,不改后端协议、不重启服务。
  • 独立质量检查发现 UUID 正则仅覆盖 v1-v5,会漏掉 UUID v7;需要改为通用 UUID 形状判断。
  • 静态源码契约不足以证明多 spawn 行为;需要提取并执行实际纯函数源码,覆盖独立 prompt 与 wait/close 保留。
  • 后续状态会携带归一化空标题字段;合并时只有新状态含可读标题才允许覆盖旧标题。
  • 归一化 entry.label 可能由 prompt 派生,必须携带 hasReadableSourceTitle 标记区分协议标题和派生标题。
  • 当前真实会话持久化数据只剩一个 receiverThreadIds: [] / agentsStates: {} 的 wait 工具,说明不能只依赖同 ID 的历史工具快照。
  • closedCollabAgentIds 只能标记已知 ID 的状态;需要额外缓存 ccweb_mcp_child_agent_update.child 的最后结构化状态,才能在空 wait/close 载荷中重建卡片。
  • 当前工作树另有“放开图片数量限制”改动,涉及 CHANGELOG.md、README*.md、public/app.js、server.js、scripts/regression.js,本修复必须限制在不重叠代码区并避免格式化整文件。
  • 独立复核确认实时缓存修复后,renderMessages() 会清空缓存;若历史只有空 close/wait,刷新仍退化为工具 ID。
  • 服务端 updatePersistedCcwebMcpChildTool 只按 child.spawnToolId 查找工具;真实会话缺少该 spawn 工具时返回 null,未把 child 状态写入历史。
  • 后端兜底应只选择最近的 collab_agent_tool_call,不得把 child 合并进普通工具。
  • 2026-07-15 本机 PM2 ccweb 已实际重启并在线;其他机器仍显示旧样式属于发布物/部署路径问题,不是本机进程未重启。
  • CentOS 7 单文件发布必须重新运行 scripts/build-single-exe.js;该流程会在打包前复制 public/ 运行时资源,源码更新不会自动进入旧 tar.gz。
  • 本机 dist-exe/cc-web-bun-linux-x64-baseline.tar.gz 已包含最新静态资源:tar 内 app.js / style.css 与源码 SHA-256 完全一致,并含 collab-agent-item-description、两行 clamp 和关闭状态缓存代码。
  • 单文件运行时从二进制同目录的 public/ 加载资源;只替换 cc-web 二进制、保留旧 public/,或设置 CC_WEB_APP_DIR/CC_WEB_PUBLIC_DIR 指向旧目录,都会继续显示旧样式。
  • 旧历史会话本身若只保存 thread ID、没有 title/taskDescription,即使加载新前端也只能显示 ID ... 且没有简介;需要用新部署后新建的子代理验证,不能只看旧历史卡片。
  • 2026-07-16 确认同一版本存在两套事件链路:完整 spawnAgent 会以 collab_agent_tool_call 进入 mergeCollabAgentTools();原生 subAgentActivity 仅在服务端用于线程恢复,前端不会把它合并成富卡片。
  • mergeCollabAgentTools() 明确过滤 toolKind(tool) === 'collab_agent_tool_call';因此 subAgentActivity + 空 wait 会分别退化为原始折叠工具条和 ID call_... 卡片。
  • 修复应在进入渲染前将 agentThreadId、agentPath、活动 kind 归一为结构化子代理状态,并避免原始活动事件重复渲染。
  • 真实会话中的 subAgentActivity 输入与结果都只包含 kind/agentThreadId/agentPath,未携带 spawn prompt;因此历史数据能恢复线程 ID、状态与角色标题,但不能凭空恢复完整任务简介。
  • 同一消息里随后出现的 wait 已被转换为 collab_agent_tool_call,但 receiverThreadIds 和 agentsStates 均为空,说明应将前置活动事件作为该 wait 的恢复来源。
  • 扫描现有会话得到 41 条 subAgentActivity:活动类型只有 started 与 interacted,输入字段稳定为 type/id/kind/agentThreadId/agentPath,均无 prompt;interacted 应保持运行态。
  • Phase 8 复审已通过;计划已明确字段映射、原始工具条与 ID call_... 去重、baseline 二进制 smoke test 和 tarball 核验。
  • 前端所有历史、恢复流和实时流都通过 toolKind() 分流;让它把 raw subAgentActivity 识别为协作显示工具,可同时复用现有合并、富卡片渲染和普通工具过滤逻辑,避免在三个调用点分别硬编码。
  • normalizeCollabAgentData() 是补齐活动字段的最小归一入口:从 agentThreadId 构建 receiver/state,从 agentPath basename 构建标题/角色,从活动 kind 映射状态,并按真实字段保留 prompt。
  • 新事件还应在 lib/codex-app-runtime.js 的 itemKind/itemInput/itemResult 层输出 collab_agent_tool_call 结构;这样旧前端也能把新会话视为富卡片,同时保留 input.type=subAgentActivity 供服务端恢复线程路由。
  • 首轮生产实现已让定向行为回归通过;人工审查仍需确认三项最小范围边界:空 wait 对整体头部状态的覆盖、agentPath 同时填充 role 导致标题/页脚重复、通用 tool_end 全量增加 name/input 的必要性。
  • 独立质量检查确认首轮实现仍有高风险缺口:完成态空 wait 会覆盖整体头部为已返回但 child 仍运行;runtime completed 不带 prompt 时会直接替换 started input,刷新后简介丢失。
  • 另有两个中风险边界:agentPath basename 回填 role 会导致标题/footer 重复;仅凭 name 匹配 subAgentActivity 会把无 agentThreadId 的同名普通工具误归类。
  • 第二轮已改为子状态优先聚合整体状态、runtime 活动输入结构化合并、agentPath 仅提供标题、activity 匹配必须存在 threadId;新增边界回归均通过,等待原检查代理复核。
  • 原检查代理复核时把 item/completed 误等同于 child completed;真实会话反证是 input.kind=started 的活动工具本身 done=true,因此 transport item 生命周期不能覆盖 activity kind 的 child 生命周期语义。
  • 正确契约:completed 通知缺少新 kind 时继承 previous activity kind/status;只有活动 kind 明确为 completed/returned/failed/closed 时才改变 child 终态,同时仍保留 started prompt。
  • 用户明确要求所有子代理统一成完整标题+简介卡片。上游 raw activity 无法追回真实 prompt,因此展示层需以 agentPath/task name 生成可读标题和明确标注的兜底简介,真实 prompt 仍保持最高优先级。
  • 富卡片独立复核发现 collabAgentStateEntries 会重新推断并覆盖 hasReadableSourceTitle:false,导致 prompt 派生的 snake_case 标题被误翻译;该标记必须贯穿 merge、entry 与 render。
  • 最终实现只美化协议/agentPath 来源的自动任务名;prompt 派生标题的 hasReadableSourceTitle:false 会贯穿 merge→entry→render,不被误翻译。
  • 最终 HTTP app.js 与源码 SHA-256 均为 0b3a14a543fa819837eb4d1bf007aa4929d52844af8624696d5f74afe8b7891e,响应为 Cache-Control: no-store, max-age=0,刷新页面即可加载,无需为纯静态改动中断其他运行对话。
  • 最终 baseline tar SHA-256 为 c85202fa3ee989689aef3821b6860b1a356267180aa79858140849599f8504d4,MCP initialize smoke test 成功。