From 01a4f61d622f73f1b30ffa826e9af055493e9bef Mon Sep 17 00:00:00 2001 From: cfdaily Date: Tue, 26 May 2026 23:39:57 +0800 Subject: [PATCH] auto-sync: 2026-05-26 23:39:57 --- .../distill-cards-batch2-simayi-mixed.md | 538 ++++++++++++++++++ 1 file changed, 538 insertions(+) create mode 100644 docs/research/distill-cards-batch2-simayi-mixed.md diff --git a/docs/research/distill-cards-batch2-simayi-mixed.md b/docs/research/distill-cards-batch2-simayi-mixed.md new file mode 100644 index 0000000..525be3e --- /dev/null +++ b/docs/research/distill-cards-batch2-simayi-mixed.md @@ -0,0 +1,538 @@ +# 经验卡片集 — 批次2 司马懿纠正 + 庞统经验混合 + +> 数据源:151 个片段(庞统经验 21 条 + 司马懿纠正 122 条 + Sanguo Mail 纠正 8 条) +> 归纳时间:2026-05-26 +> 覆盖时间段:2026-05-06 ~ 2026-05-26 + +--- + +## 汇总表 + +| # | 分类 | 严重度 | 频率 | 来源 | 核心教训 | +|---|------|--------|------|------|----------| +| 1 | 代码评审 | high | 5+ | simayi-correction | 评审必须验证最终代码,不能只审方案 | +| 2 | 代码评审 | high | 3+ | simayi-correction | 状态机/枚举值不一致是高频 Bug 根源 | +| 3 | 系统设计 | high | 3 | simayi-correction, experience | 评审者自我纠正:承认判断错误比坚持错误更有价值 | +| 4 | 系统设计 | high | 4+ | simayi-correction | 设计文档-代码一致性审查不能省 | +| 5 | 系统设计 | medium | 2+ | experience | "一键三连"闭环标准:文档→代码→最终确认 | +| 6 | 系统设计 | high | 3 | simayi-correction | Counter/锁的生命周期必须贯穿完整调用链 | +| 7 | 系统设计 | high | 2 | simayi-correction | 进程退出 ≠ 资源释放:on_complete 回调时序是关键 | +| 8 | 编排调度 | high | 5+ | simayi-correction | 续杯(retry)机制是最大的假死来源 | +| 9 | 编排调度 | medium | 3 | simayi-correction | 广播路径与单播路径必须行为一致 | +| 10 | 编排调度 | medium | 3+ | simayi-correction | E2E 测试要用真实环境,不能只测单元 | +| 11 | Agent 行为 | medium | 4+ | simayi-correction | Agent 认领任务前必须检查角色匹配 | +| 12 | Agent 行为 | high | 2 | simayi-correction | inform 类型邮件不应触发完整 Agent 执行 | +| 13 | 沟通协作 | medium | 3 | pangtong-correction, simayi-correction | 回答用户问题要直接,不要绕弯子 | +| 14 | 系统设计 | medium | 2 | simayi-correction | stdout JSON 解析路径必须实测验证 | +| 15 | 经验总结 | low | 2 | experience | 跨项目调研的实践对照表要做落地映射 | + +--- + +## 卡片 1:评审闭环必须包含最终代码确认 + +```yaml +--- +category: "代码评审" +tags: [review, 闭环, 最终代码] +severity: "high" +frequency: 5 +sources: ["simayi-correction", "experience"] +--- +``` + +### 场景 +多步骤开发中,方案评审通过后,实现阶段可能有微调。如果评审者只确认了方案而没看最终代码,Bug 可能被遗漏。 + +### 错误做法 +庞统在 M2 阶段让司马懿 review 了 Checkpoint 和 Hooks 的**方案**,但实现后只说"已采纳建议",没发最终代码让司马懿确认。用户发现后指出: +> "一键三连最终肯定是以司马懿 review 完你的最终成果物收尾的,不是他 review 完你的方案就算完事" [pangtong/experience] + +### 正确做法 +**一键三连 = 改文档 → 改代码 → 司马懿确认最终代码片段**。每个方案落地后,必须把最终代码(不是方案描述)发给评审者确认。司马懿在评审中多次明确引用代码行号做交叉验证,这种精度只有看最终代码才能做到。 + +### 关键细节 +- "已采纳"不等于"已验证"——采纳后的代码可能引入新问题 +- 司马懿多次在代码评审中发现方案评审没暴露的 Bug(如 `_do_retry` 续杯失效) +- 续杯评审中,司马懿看到最终代码才发现 on_complete=None 导致幻觉门控丢失 + +### 反面教训 +未确认最终代码导致 Checkpoint 实现与设计不一致,返工修复。 + +--- + +## 卡片 2:状态机枚举值不一致是高频 Bug 根源 + +```yaml +--- +category: "代码评审" +tags: [状态机, 枚举, 一致性] +severity: "high" +frequency: 3 +sources: ["simayi-correction"] +--- +``` + +### 场景 +系统有多处引用任务/节点状态值(数据库查询、状态转换、恢复逻辑),如果枚举定义与实际使用不一致,会导致静默失败。 + +### 错误做法 +M1 遗留 Bug P0-2:`get_all_executing_tasks` SQL 查询用 `'executing'`,但实际枚举值是 `'working'`,导致重启恢复时 working 节点被遗漏。 +> "启动恢复查询用节点状态包含 'executing',但实际节点状态枚举中无此值(应为 'working')" [pangtong/simayi-review] + +E2E 测试发现 `failed→pending` 转换不清 `assignee`,与另一路径 `ticker._transition_status` 的行为不一致。 + +### 正确做法 +1. 状态枚举集中定义,所有引用点从枚举取值,硬编码字符串零容忍 +2. 状态转换函数只保留一个入口(如 `_transition_status`),禁止分散在多个模块 +3. 评审时重点检查:新代码中的状态值是否与枚举定义一致 + +### 关键细节 +- 司马懿在 counter v2.1 评审中发现 `max_per_agent=2` vs 设计文档的 `1`,也是同类问题 +- auto-sync 可能静默修改配置文件,需要与设计文档对照 + +### 反面教训 +状态不一致导致任务永久卡住(P0-1)和重启恢复失败(P0-2)。 + +--- + +## 卡片 3:评审者自我纠正是高质量评审的标志 + +```yaml +--- +category: "代码评审" +tags: [自我纠正, 评审质量, 诚实] +severity: "high" +frequency: 3 +sources: ["simayi-correction", "mail"] +--- +``` + +### 场景 +评审者在审查代码时可能做出错误判断。高质量的处理不是掩盖,而是主动承认并修正。 + +### 错误做法 +无。此处记录的是正确做法的范例。 + +### 正确做法 +庞统在评审 spawner-monitor 时发现两处自己之前的判断有误,主动发邮件给司马懿修正: +> "修正 1: 问题4 recent_compact 不是死代码,是设计实现遗漏" — 原判断"建议删除",修正为"设计文档 §B2/B3 明确要求" [pangtong/mail] + +司马懿回复: +> "你说得对,我判断错了。设计文档 §B2/B3 明确要求区分 compact 进行中和进程卡死" [simayi/mail] + +### 关键细节 +- 评审者翻回设计文档交叉验证,是发现误判的有效手段 +- 庞统和司马懿都在同一次评审中做了自我纠正——这说明交叉验证机制在工作 +- 修正邮件明确标注"修正"而非静默修改,保留了审计轨迹 + +### 反面教训 +如果不主动修正,错误判断会被当作已确认结论传播,后续实现可能基于错误假设。 + +--- + +## 卡片 4:设计文档-代码一致性审查不可省 + +```yaml +--- +category: "系统设计" +tags: [设计文档, 代码一致性, 三层审查] +severity: "high" +frequency: 4 +sources: ["simayi-correction"] +--- +``` + +### 场景 +迭代开发中设计文档可能更新不及时,或者代码实现偏离设计。需要 PRD→设计→代码的三层一致性审查。 + +### 错误做法 +spawner-monitor 实现中,设计文档 §B2(compact 进行中继续等)在代码中完全遗漏。司马懿初评时也未发现,直到庞统重新读设计文档才暴露: +> "代码只实现了 B1/B3/B4,B2 遗漏了。recent_compact 是 B2 实现的数据基础" [pangtong/mail] + +### 正确做法 +1. 每次代码评审前,先对设计文档逐条检查实现覆盖度 +2. 设计文档用明确编号(§B1/B2/B3)便于逐条追踪 +3. 庞统安排了 "背靠背一致性审查":PRD→设计→代码全覆盖审计 +4. 司马懿的核心职责就是做这种三层对照 + +### 关键细节 +- 庞统专门发了 #311 邮件请求"PRD→设计→代码三层一致性审查" +- 司马懿在 counter 生命周期评审中发现设计说 crash 3 次标 failed,但代码只 release counter 无计数 + +### 反面教训 +设计-代码不一致导致假死检测失效,系统在 compact 后无法区分"还在跑"和"卡死了"。 + +--- + +## 卡片 5:方案确认的完整闭环标准 + +```yaml +--- +category: "系统设计" +tags: [闭环, 一键三连, 确认标准] +severity: "medium" +frequency: 2 +sources: ["experience"] +--- +``` + +### 场景 +多方案并行开发时,哪些方案算"完成"容易模糊。 + +### 错误做法 +庞统在 M2 阶段同时推进多个方案,只跟踪了"方案评审"状态,没跟踪"最终代码确认"状态。用户追问才发现 Checkpoint 和方案 C 的代码未闭环。 + +### 正确做法 +**一键三连收尾标准**(用户明确定义): +1. 改文档(设计/方案) +2. 改代码(实现) +3. **司马懿 review 并确认最终代码片段** + +每步完成都要有明确证据(邮件编号、代码片段引用)。 + +### 关键细节 +- 状态跟踪表要包含三列:方案评审 / 最终代码确认 / 状态 +- 司马懿的确认必须是具体的("代码片段与实际改动一致"),不是笼统的"通过" + +### 反面教训 +未闭环的方案被标记为"已完成",实际遗漏了代码审查环节。 + +--- + +## 卡片 6:Counter/锁的生命周期必须贯穿完整调用链 + +```yaml +--- +category: "系统设计" +tags: [counter, 锁, 生命周期, 资源管理] +severity: "high" +frequency: 3 +sources: ["simayi-correction"] +--- +``` + +### 场景 +Agent 并发控制需要 counter/锁机制。如果 counter 的 acquire-release 不成对,会导致永久占满或双重释放。 + +### 错误做法 +spawner `_handle_exit` 中 retry 路径提前调 `on_complete("retry_release")` 释放 counter,但续杯 spawn 时 counter 已释放,导致同一 Agent 被并发 spawn 多次: +> "retry 路径提前调 on_complete("retry_release") 释放 counter,导致续杯 spawn 时 counter 已空" [simayi/mail] + +司马懿在评审中发现 `_do_retry` 中 counter 仍被占用但 on_complete=None,导致续杯永远无法 acquire。 + +### 正确做法 +1. **Counter 贯穿 retry 链**:acquire 在 spawn 前,release 在最终退出(done/failed)后 +2. Retry 不释放 counter,而是复用同一个 counter slot +3. 司马懿建议的 cooldown 机制:release 后短期冷却,防止立即 re-acquire 导致抖动 +4. 三层控制:cooldown → global limit → per-agent → per-session + +### 关键细节 +- 所有 `release` 调用都要带 session_id(counter v2.1 的教训) +- on_complete 回调的时序:进程退出 ≠ 回调完成 +- 广播 spawn 路径也要 catch AgentBusyError + +### 反面教训 +counter 提前释放导致 zhipu API 429(rate limit 被打爆),Gateway 假死。修复后 counter 泄漏导致续杯死循环。 + +--- + +## 卡片 7:进程退出 ≠ 资源释放 + +```yaml +--- +category: "系统设计" +tags: [进程管理, 回调时序, on_complete] +severity: "high" +frequency: 2 +sources: ["simayi-correction"] +--- +``` + +### 场景 +异步系统中,子进程退出和回调执行不是原子操作。如果假设进程退出时资源已释放,会出现竞态条件。 + +### 错误做法 +spawner 在 retry 时:进程退出 → on_complete 未调用 → counter 仍占用 → spawn_full_agent 的 can_acquire 返回 False → AgentBusyError → 续杯永远不会成功。 + +### 正确做法 +1. 在 `_do_retry` 中手动释放 counter,并将 on_complete 设为 None 防止 double release +2. 资源释放应该有明确的触发点,不能依赖"进程退出自然释放" +3. 司马懿在评审中强调:需要确认每条退出路径都有对应的资源释放 + +### 关键细节 +- on_complete=None 后续杯 spawn 完成无幻觉门控,靠 ticker 超时兜底——影响可接受但需要记录 +- 安装目录同步是必须的检查项(司马懿每次评审都验证) + +### 反面教训 +未处理回调时序导致续杯死循环,任务永远无法完成。 + +--- + +## 卡片 8:续杯(retry)机制是最大假死来源 + +```yaml +--- +category: "编排调度" +tags: [续杯, retry, 假死, 死循环] +severity: "high" +frequency: 5 +sources: ["simayi-correction"] +--- +``` + +### 场景 +任务执行超时后需要 retry("续杯")。如果 retry 机制本身有 Bug,会导致无限重试或永久卡住。 + +### 错误做法 +多个 Bug 叠加导致续杯死循环: +1. retry_count 在续杯中永远不变(retry_count=1/3),续杯永不停 +2. Mail 续杯用 RETRY_PROMPT(含 review 标记指令),Agent 标了 review,但 _mail_auto_complete 只认 done +3. 续杯创建新 session 而非复用 main session,每次重试都是全新上下文,丢失之前工作 + +### 正确做法 +1. 续杯模板必须专用(MAIL_RETRY_PROMPT),明确禁止状态转换命令 +2. retry_count 必须在每次续杯时递增,max_retries 兜底 +3. 续杯应复用 session 保持上下文连续性 +4. 司马懿在 Bug-7 评审中确认:retry 应复用 main session,每次重试不创建新 session + +### 关键细节 +- 续杯模板的"不要执行状态转换"指令是关键——Agent 容易自作主张标 done +- 司马懿在 Bug-8 评审中发现 use_main_session 在三处(主 dispatch、legacy broadcast、retry)必须统一 + +### 反面教训 +续杯死循环阻塞 tick,导致整个调度停滞。PM2 restart 后旧 session 仍在续杯,新 session 又被创建,资源爆炸。 + +--- + +## 卡片 9:广播路径与单播路径行为必须一致 + +```yaml +--- +category: "编排调度" +tags: [广播, 单播, 路径一致性] +severity: "medium" +frequency: 3 +sources: ["simayi-correction"] +--- +``` + +### 场景 +任务调度有两条路径:指定 Agent 的单播和广播认领。如果两条路径的行为不一致,某些任务类型会系统性地出问题。 + +### 错误做法 +广播路径 `ticker._broadcast_claim` 调 `spawn_full_agent` 时没传 `task_id` 和 `db_path`,导致续杯时无法查询任务状态,retry_count 永远不变: +> "广播路径不传 task_id/db_path → 续杯时 retry_count=1/3 永远不变" [simayi/mail] + +### 正确做法 +1. 所有 spawn 路径(单播、广播、retry)必须传递完整的上下文参数 +2. 评审时重点检查:新功能是否覆盖了所有 spawn 路径 +3. 司马懿多次提醒:广播 spawn 路径也要 catch AgentBusyError + +### 关键细节 +- Mail 变广播导致所有 Agent 假死的事件就是路径不一致的典型案例 +- 司马懿在 v2.7.2 Pipeline 重构评审中建议统一 TickResult 返回值 + 方法注册 + +### 反面教训 +广播路径缺失参数导致续杯死循环,影响所有通过广播认领的任务。 + +--- + +## 卡片 10:E2E 测试必须用真实环境 + +```yaml +--- +category: "编排调度" +tags: [E2E测试, 真实环境, 集成测试] +severity: "medium" +frequency: 3 +sources: ["simayi-correction"] +--- +``` + +### 场景 +单元测试只能验证单个模块逻辑。编排系统的 Bug 往往出在模块交互(spawn → 执行 → 续杯 → 状态转换),只有真实环境 E2E 能暴露。 + +### 错误做法 +早期只跑了单元测试,部署后发现大量中间状态卡住的任务。用户发现: +> "dashboard的任务中,大量的停在了中间阶段" [user/simayi-correction] + +### 正确做法 +1. E2E 测试走真实 Ticker + 真实 Agent spawn,不手动推动状态 +2. 测试用例覆盖完整生命周期:创建→调度→执行→续杯→完成/失败 +3. 司马懿独立跑 E2E 测试并做根因分析,与庞统的修复做交叉验证 +4. 每次修复后全量重跑 E2E(不是只跑失败的用例) + +### 关键细节 +- 司马懿的 E2E 报告格式:通过/失败计数 + 每个失败用例的根因分析 +- 测试从 6/10 → 8/10 → 9/10 → 10/10 的渐进修复过程证明 E2E 驱动开发的有效性 + +### 反面教训 +未做 E2E 导致假死问题在生产环境中才暴露,排查成本远高于测试阶段。 + +--- + +## 卡片 11:Agent 认领任务前必须检查角色匹配 + +```yaml +--- +category: "Agent 行为" +tags: [认领, 角色匹配, 任务分配] +severity: "medium" +frequency: 4 +sources: ["simayi-correction"] +--- +``` + +### 场景 +黑板广播任务时,所有 Agent 都能看到。如果审查者(司马懿)认领了编码任务,会导致角色错配。 + +### 错误做法 +simayi-challenger(审查者)认领了 coding 类型任务: +> "问题1:Agent 角色错配(P1)— simayi-challenger(审查者)认领了 coding 任务" [pangtong/mail #337] + +数据中有大量司马懿被广播认领 E2E coding 任务的记录(frag_0076, frag_0305, frag_0320 等),说明这是系统性问题。 + +### 正确做法 +1. 任务模板中明确角色匹配规则:只认领符合专长的任务 +2. 评审/审查类角色不应认领编码任务 +3. 任务描述中包含"只认领符合你专长的任务"的提示,但 Agent 仍然会忽略 + +### 关键细节 +- 这个问题出现了 20+ 次(大量 E2E 广播任务被司马懿认领) +- 根因是黑板没有角色过滤机制,完全靠 Agent 自律 + +### 反面教训 +角色错配导致编码任务被审查者执行,产出质量不符合预期。 + +--- + +## 卡片 12:inform 类型邮件不应触发完整 Agent 执行 + +```yaml +--- +category: "Agent 行为" +tags: [邮件, inform, 资源浪费] +severity: "high" +frequency: 2 +sources: ["simayi-correction", "mail"] +--- +``` + +### 场景 +Agent 之间的邮件有两种:需要回复的(request)和纯通知的(inform)。如果 inform 也触发完整 Agent 执行,会浪费大量 token 和 counter 资源。 + +### 错误做法 +庞统的 daemon 用 `openclaw agent --agent simayi-challenger --timeout 300` 处理 inform 邮件,Agent 被完整 spawn 执行,310s 超时后重新投递: +> "daemon 用 openclaw agent --agent simayi-challenger --timeout 300 处理 inform 类型邮件,310s 超时后重新投递" [simayi-correction] + +### 正确做法 +1. Mail 类型简化为两种:inform(通知)和 request(需要回复) +2. inform 类型由 ticker 直接标 done,或用轻量 prompt("读完标 done")让 Agent 感知但不做完整执行 +3. 默认类型是 request,inform 是显式指定的特殊场景 + +### 关键细节 +- 庞统和用户讨论后确认:inform 仍让 Agent 看到内容(可能包含重要信息),但 prompt 告诉它不需要回复 +- 这种设计比 ticker 直接标 done 更合理 + +### 反面教训 +inform 触发完整执行 + 超时重投递,形成死循环,消耗大量 API 调用和 token。 + +--- + +## 卡片 13:回答用户问题要直接,不要绕弯子 + +```yaml +--- +category: "沟通协作" +tags: [沟通, 直接回答, 效率] +severity: "medium" +frequency: 3 +sources: ["pangtong-correction", "experience"] +--- +``` + +### 场景 +用户提出具体问题时,Agent 有时回避核心问题,用相关信息绕弯子。 + +### 错误做法 +庞统在讨论 compact 卡死问题时,反复讨论"compact 发生的概率"和"v1 vs v2 的区别",而用户已经明确说了"集中讨论 compact 发生后如何处理": +> "你说得对,我一直在说废话。子进程就是 `openclaw agent`,等子进程就是等 `openclaw agent` 执行完" [pangtong/experience] + +> "别绕了,我都说过了,请你集中在 compact 发生之后如何处理" [user] + +### 正确做法 +1. 先直接回答用户的问题(哪怕答案是"不能/不知道") +2. 不确定时说"不能",然后说明可以做什么 +3. 庞统最终的模式值得学习:"处理方式就三个问题:超时后怎么处理、重试用什么 session、重试几次后放弃。这就是全部。没有更复杂的了。" + +### 关键细节 +- "不能区分超时原因"本身就是一个有用的答案 +- 不需要区分原因也能给出处理方案——区分原因只对监控有意义 + +### 反面教训 +绕弯子浪费多轮对话,用户反复追问同一问题。 + +--- + +## 卡片 14:stdout JSON 解析路径必须实测验证 + +```yaml +--- +category: "系统设计" +tags: [JSON解析, stdout, 实测] +severity: "medium" +frequency: 2 +sources: ["simayi-correction"] +--- +``` + +### 场景 +`openclaw agent --json` 的输出结构可能随版本变化。如果解析路径是猜的而非实测的,会导致静默失败。 + +### 错误做法 +spawner 代码取 `data.response.meta.transport`,但实际 `openclaw agent --json` 的顶层结构是 `{ response: { meta: { transport, ... } } }`: +> "P0:_parse_stdout_json 解析路径错误(根因)— openclaw agent --json 输出格式是 { response: { meta: { transport, ... } } } 但代码取的路径不对" [pangtong/mail] + +### 正确做法 +1. 解析外部命令输出前,先用实际命令验证输出格式 +2. 评审时要求看到实测输出样例 +3. 司马懿在 Spawner v3.0 评审中指出 JSON 解析路径需验证:`data.result.meta.executionTrace` 是新路径,需确认 + +### 关键细节 +- 这个 Bug 从第一天就存在("从第一天就存在的根因 bug") +- 静默失败比报错更危险——解析不到数据时走了 fallback,掩盖了问题 + +### 反面教训 +解析路径错误导致 stdout 信息丢失,所有依赖 stdout 判定的功能(如幻觉门控)失效。 + +--- + +## 卡片 15:跨项目调研的实践对照要做落地映射 + +```yaml +--- +category: "经验总结" +tags: [调研, 对照表, 落地映射] +severity: "low" +frequency: 2 +sources: ["experience"] +--- +``` + +### 场景 +Agent 调研多个开源项目的最佳实践后,需要将发现映射到自己的项目架构中。 + +### 错误做法 +庞统调研了 OpenAI Agent SDK、LangGraph、Claude Code 三个项目,产出了详细的对照表,但部分条目只停留在"可借鉴"层面,没有明确"怎么做"。 + +### 正确做法 +1. 调研产出必须包含"moziplus 可借鉴点"列,明确优先级(M2 直接借鉴 / 够用 / 暂不需要) +2. 标注哪些是**可直接复用的模式**(如 Lifecycle Hooks → on_node_start/end),哪些需要适配 +3. 司马懿在评审 Pipeline 重构时引用了业界调研,确认"Temporal 模式最接近我们" + +### 关键细节 +- 调研本身就是 Agent 经验声明的一种形式 +- 庞统的对照表格式(优秀实践 / 来源 / 核心模式 / 可借鉴点)是好的模板 + +### 反面教训 +没有落地映射的调研容易变成"资料搬运",无法转化为架构改进。