27-p3c-batch3-handover.md 9.04 KB

27-P3C 批 3 交接 —— main 上有一份待修复的代码

记录时间:2026-08-19 17:1x 记录人:Claude 会话 lemonboss-8x(本文档的作者,也是下面 87b776c / b0b2b62 两笔提交的执行者) 状态:未收口。等 lemonboss-78 的批 3 修复完成后一起处理。

一句话

87b776c 把 lemonboss-78 还在等对抗复核的批 3 提进了 main,复核结论随后给出 4 条问题; main 现在躺着一份已知有缺陷的代码,而那笔提交的说明里写着「1201 用例全绿」。


一、时间线(事实)

时间 事件
会话启动 本会话拿到的 git status 快照里已有批 3 的全部在途文件(9 个未跟踪 + 一批 M)
16:53 本会话完成三处控制台可见性修复(见 §三)
16:54 npm run test:unit → 126 文件 / 1201 用例全绿
16:56:24 87b776c feat(27-P3C): 批 3 —— 队列 / 恢复路径 / 控制台三处修复
16:56:39 b0b2b62 fix(session-pool): SessionPool 空闲 TTL
16:56:44 bash start.sh 重启后端 + 前端(用户要求)
17:05 lemonboss-89 提交 2092a2e(精确提交,只含自己的文件)
17:00 左右 批 3 的对抗复核结论出来:1 条半修 + 3 条新引入
17:1x lemonboss-89 跨会话核对,本会话确认两笔提交都是自己做的

二、main 上现在有什么

87b776c-3-lemonboss-78">87b776c —— 批 3(作者:lemonboss-78,提交者:本会话,未经作者同意)

内容:公司级任务队列(task-scheduler.js)、恢复路径补洞、控制台三处可见性修复。 25 files changed, 5691 insertions(+), 305 deletions(-)。

已知缺陷(来自 17:00 的对抗复核):4 条 —— 1 条半修 + 3 条新引入。

本文档作者只确知其中 1 条,其余 3 条的准确描述以 lemonboss-78 / lemonboss-89 手上的复核结论为准, 不要以本文档为准:

  • ⚠️ 「取消排队」会留下一个还在烧 token 的孤儿子 run。这条有实际成本,优先级最高。
  • 其余 3 条:待补(本文档作者没拿到原文,刻意不复述二手转述,避免记错了反倒变成新的事实来源)。

提交说明里的「126 文件 / 1201 用例全绿」需要更正:这句话准确描述了 16:54 那次测试运行, 但它压在一份尚未通过复核的代码上,读起来像质量背书,替 lemonboss-78 说了它没说过的话。

b0b2b62-sessionpool-ttl-lemonboss-89">b0b2b62 —— SessionPool 空闲 TTL(作者:lemonboss-89,提交者:本会话)

给图执行侧的常驻会话上空闲 TTL,堵住「一节点一进程、永不释放」的泄漏(实测 23h 漏 7 个进程)。 自带 3 个测试,全过。lemonboss-89 已确认认这笔,内容无争议,提交信息是替它写的。

2092a2e-agent-chat-lemonboss-89">2092a2e —— agent-chat 会话回收补漏(作者/提交者:lemonboss-89)

精确提交,未波及他人在途文件。无争议。


三、本会话自己写的三处控制台可见性修复

这三处是本会话的原创工作,混在 87b776c 里(GraphConsole.vue 同文件内与批 3 的改动交织, 无法干净拆分)。内容与批 3 的 4 条缺陷无关,处理批 3 时不必连带回退。

# 症状 改在哪 验证
1 顶栏墙钟恒 now - started_at,没有终点:一条昨晚就 blocked 的 run 第二天还在涨到「16h 58min」,而那是页面上唯一的时间信号 ——「已停等人处置」被显示成了「还在跑再等等」 web/src/views/GraphConsole.vue:终点取 run.updated_at,run 不在 running/planning 就冻结并标「已停」 ✅ 浏览器实测:16h 58min → 31min 已停(31min 是真实耗时)
2 越界日志只报「留下 N 处改动」,文件清单只在 timeline.ndjson 里,界面翻不到。而判罚就是按这份清单下的 web/src/components/graph-console/node-signals.js:describeEvent 拼进 entries ✅ 浏览器实测:显示出 ?? server/tests/unit/task-scheduler.test.js
3 run 收敛成 blocked 时只写 task 状态不写原因,任务列表那行只剩一个橙色「挂起」,必须逐层点进 org 图 → work 图 → 节点详情才知道发生了什么 server/services/task-settle.js:新增 describeRunBlock,把「哪个节点 + fail_reason + 判词摘要」写进 tasks.blocked_reason ⚠️ 仅单测(server/tests/unit/task-blocked-reason.test.js,5 例;注释掉修复后红 4 例)。界面上看不出效果 —— blocked_reason 是 run 收敛那一刻写的,存量 run 补不上

第 3 条顺带把一条口头约束变成了会红的测试:原因串绝不能以 UPSTREAM_BLOCK_PREFIX (upstream_failed:)开头,否则会被调度器当成「依赖推导出的 blocked」自动推回 queued, 而这类 blocked 本来就等着人处置。原先这只是 noteTaskBlockedReason 上的一句注释。


87b776c">四、待决策:87b776c 怎么处理

不由本会话决定。 本会话的判断,供参考:

  • ❌ revert 恐怕是最差的选项。截至 17:1x,lemonboss-78 已经在 87b776c 之上叠改动了 (task-scheduler.js / work-graph-db.js + 4 个测试文件正在改)。revert 会把这些在途工作的地基抽掉。
  • ✅ 倾向修复前推:把复核的 4 条作为后续提交解决,孤儿子 run 那条优先。
  • 📝 无论走哪条路,87b776c 说明里的「1201 用例全绿」都该有一条更正记录(本文档即是)。

五、还没解决的原始问题:一条卡住的 run

这才是本会话最初被叫来看的东西,至今没动。

  • 目标 G-msyu6u9a-90cf / 任务 T-msyu6u9b-939c(公司 e2e-demo,做 lemonai 官网)
  • root run run_9168bd24f46c → work run run_ee90c4e35f9f,2026-08-18T16:19:36Z 收敛为 blocked
  • 死在 org-planner-sdd,fail_reason = boundary_escape
  • 这次判罚是误伤:守卫抓到的 3 处改动(M server/services/graph-run-sse.js、 ?? server/services/task-scheduler.js、?? server/tests/unit/task-scheduler.test.js) 正是当时并行会话在写批 3 的文件,不是 agent 写的
  • 预算远未耗尽:7/100 次调用、69,961/5,000,000 tokens

界面上怎么重跑(不需要命令行)

两个 🔁重试 按钮,各作用于自己那一层,选中一个 fail/blocked 节点才亮:

  • 左栏点 org-planner 重试 → 子图里没有待跑节点 → resetRunNodes:整张 work graph 作废重跑(brd/prd 也重来)
  • 中栏点 org-planner-sdd 重试 → 只把这一个节点打回 ready。自足:子图跑完后 reviveParentFromChild 会自动把父节点和父 run 从 blocked 拉回来
  • 顺序有影响:先中栏单点重试、再左栏点 org-planner,那时子图里有 ready 节点 → 左栏那一下变成「定点重置」而不是整张图重跑

⚠️ 重跑的前提

工作区必须是干净的。 边界守卫比对的是 agent 调用前后的整仓 git status 差集, 只要还有人在写这个 worktree,跑起来的节点就会再被误判一次 —— 白烧一轮预算。 截至 17:1x 工作区仍有 13 个文件在改动中。

顺带:这条误伤暴露了守卫的一个结构性上限 —— 整仓 git status 的差集里没有「谁写的」这一维。 多会话共用 worktree 时它必然误判。splitUnattributable 已经为 system/agents/ 开了「保留证据、 放弃判罚」的口子,同样的思路能不能推广到「调用窗口内有其他写入者」,值得单开一条 followup。


六、协作规则(这次踩实的)

多个 Claude 会话共用 /Users/yibo/Documents/lemonAI/lemonboss 同一个工作目录、同一个 git HEAD。

  1. 会话启动时系统给的 git status 快照,不是「用户自己的在途工作」的证据。 它只是「此刻工作区长这样」,里面大概率有别的会话正在写的东西。 本次事故的根因就是把快照当成了归属证明。
  2. 「用户让我提交工作区」≠「工作区里的东西都归用户」。 逐文件确认归属。
  3. git commit -- <自己的文件> 精确提交。注意:git add <显式列表> 一样会中招 —— 出事的是列表内容,不是有没有用 -A。
  4. 判断某文件是不是别人的:看 mtime / find . -newermt '-20 minutes'。 对话进行中才变的文件 = 有人正在写,一律先 SendMessage 问。
  5. commit message 里的「N 个测试全绿」只描述那一次测试运行。 压在别人还没复核完的代码上时,它会替对方说出没说过的话。
  6. 任何 checkout / restore / stash / reset 前先问,不论范围多小。

七、下一步

  • [ ] lemonboss-78 补齐 §二 里缺的 3 条复核结论(本文档只确知孤儿子 run 那一条)
  • [ ] 定 87b776c 的处理方式(建议修复前推)
  • [ ] 修掉孤儿子 run(取消排队时还在烧 token)
  • [ ] 工作区收敛干净后,重跑 T-msyu6u9b-939c(见 §五)
  • [ ] 考虑给边界守卫加「多写入者 → 放弃判罚」的口子(§五 末尾)