测试 788/788 全绿(76 文件,起点 786),未改任何既有断言。
## 1. idleTimeoutMs 硬编码 120s(「work 节点 → success」跑不通的唯一技术原因)
agent-manager.js 里 `this.config?...?.idleTimeout || 120_000`,且 `...options`
摊在前面被下一行覆盖,两个后果叠加:
- 默认 120 秒,比 stream-executor 自己 JSDoc 写的 30 分钟(1_800_000)小一个数量级,
也和同进程 ClaudeCliProtocol 早已放到 24h 的 idle 上限完全对不上
- 调用方**无法覆写** —— 传了 options.idleTimeoutMs 也会被盖掉
真 CLI 下的后果:任何「先读几千行源码再动笔」的节点都在动笔前被杀
(readme-writer: idle timeout: no stream data for 120000ms)。
改成 调用方 > agent 配置 > DEFAULT_IDLE_TIMEOUT_MS(30min),并把常量真的定义出来
—— 上一轮 Master agent 自己诊断出这个问题也动手改了,但引用了未定义的
DEFAULT_IDLE_TIMEOUT_MS,跑起来是 ReferenceError。
## 2. W7 判据在零边最小图上失效
判「org graph 成型了没有」原先看**边数**,理由是「节点 hire() 自己就会造,
拿节点数当信号会废掉『连雇两个人第二个不入图』」——理由成立,但边只是
「writeGraph 跑过」的代理,而真跑里 orggraph-planning 裁出过一张**零条边的单节点图**,
代理当场失效:三条判据全落空 → work 层本体被写进 org_graph_nodes,
下一次下达任务时被 advanceOne 当成 org 节点执行。
改成记录**来源**而不是猜:org_graph_nodes 加 authored_by(idempotent ALTER),
writeGraph 写 'planner'、hire 写 'hire',判据看有没有 planner 写下的节点。
hire 先记的行随后被 planner 纳入时升格,反向不降级。
存量行 authored_by 为 NULL,回落到原来的边数代理,行为不变。
新增两条用例(既有 9 例造的全是有边的成型图,正好绕开这个形状),
并做过变异验证:把判据改回纯边数,两条精确变红,还原后逐字一致。
## 3. 前后端「能不能下达任务」的规则各写一份且不一致
前端 ACTIVE_RUN 含 blocked、后端 ACTIVE_ROOT_RUN_STATUS 不含(唯一索引
idx_graph_runs_one_active_root 里也没有)。后果:一家公司只要失败过一次,
控制台上就再也下不了第二个任务,而后端其实放行。
规则只留服务端一处:GET /graph-runs 返回 canDispatch / activeRootRunId,
前端照抄结果,不再自己复述取值域。字段缺失时保守放行,交给端点 409 兜底。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>