diff --git a/docs/README.md b/docs/README.md index 2590218..6010c7e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -45,7 +45,7 @@ | [system-design/45-graph-run-node-liveness-recovery.md](./done/system-design/45-graph-run-node-liveness-recovery.md) | ✅ **Part A/B/C 已实现**(2026-08-31),**Part D 有意延后**。真实事故:h3video 公司一个 `agent_call` 节点卡在 `status=running`、背后 CLI 进程已死,服务器主进程没重启——心跳(纯 LLM 驱动)、开机一次性孤儿扫描、goal/task 巡检(判据是 `blocked` 不是 `running`)、wallclock 看门狗(按预算不按存活)四层机制全盖不到;`ceo` 被转发问题后自己绕过引擎拉会话,陷入死循环。**Part A**:调查发现 `SessionPool` 是每次调用现造即回收的一次性对象,没有可查询的存活注册表,原设计不可行,改用「运行时长超阈值(默认 25 分钟)+ 只扫 `agent_call` 节点」,新函数 `sweepStaleRunningAgentCalls`/`startStaleAgentCallWatchdog`(`graph-engine.js`),5 条新单测。**Part B**:`force-fail` 端点(42 号文档已实现)本身就够用,零新后端代码,只在 `ceo/tools.md` 补了使用文档 + 明确禁止绕过引擎自拉会话。**Part C**:`ceo/heartbeat.md` 同步更新。**Part D**(节点补显式心跳字段,消除 Part A 阈值判据的误伤局限)未做,见文内「实现记录」的理由 | | [system-design/47-itemized-subtask-materialization-goal-benchmark-fallback.md](./done/system-design/47-itemized-subtask-materialization-goal-benchmark-fallback.md) | ✅ **已修复**(2026-09-02)。46 号文档 Phase 0 真实回归坐实:`acceptance.md` 在当前 `workgraph-planning` 常规划出的 org-planner 子图形状(prd/sdd/goal-benchmark/planner-validator)下结构性产不出来,`itemized` 子任务物化 0 命中。修法:物化逻辑新增兜底,`acceptance.md` 缺失时改读已被 44 号文档证实稳定产出的 `goal-benchmark.json` 的 `dimensions[]`。`task-decomposition-materialize.test.js` 5 条全过(2 条新增,用真实回归捕获的产物做测试数据) | | [system-design/48-task-acceptance-contract-binding.md](./done/system-design/48-task-acceptance-contract-binding.md) | ✅ **已实现并完成真实端到端回归,已收口**(decomposed_work 链路 2026-09-02/回归补于 2026-09-03,剩余三条路径调研收口于 2026-09-03)。承接 46 号文档 Phase 3 v2 真实回归发现的 `org-validator` 死锁:验收契约的产出被硬绑在"公司完整 org graph 一定会跑到 org-planner"这个假设上,不满足这个假设的执行路径(如轻量子任务图)无契约可读、退无可退。方案:消费端(validator 只认结构化契约、不自由判断)保持硬约束不变,产出端改成"每个 decomposed_work 子任务创建时必须 1:1 带一份验收契约"(`tasks.acceptance_contract` + `createTask` 统一校验 + `enqueueTaskRun` 落盘),真实 `org-coder`→`org-validator` 全程跑通验证。**收口时追加调研**:`task-planning`/`org-planner` 的 `acceptance_item` 物化/人类快速派单三条创建路径经核实**不需要**同款强绑定——都走完整 org graph,`workgraph-planning` 的 `benchmark` 节点"不可裁"约定已天然保证有契约,强行加会跟 46 号文档保护的 `task-planning` 极简边界、快速派单"零 LLM"定位冲突。真正残留风险是"org graph 一定含 org-planner"目前只是提示词约定非代码强制,属于 org 拓扑保证问题,不在本文档范围。安全网(发现时就地补契约)按设计仍只留原则,`decomposed_work` 链路已被主力机制完全覆盖,不为不可达场景写代码 | -| [system-design/46-mandatory-planning-and-task-decomposition.md](./done/system-design/46-mandatory-planning-and-task-decomposition.md) | ✅ **已收口**(2026-09-06)。Phase 0-5 全部实现。**Phase 1**:新 agent `subtask-planning`,钩在 `enqueueTaskRun`(显式 opt-in),产物写共享 `artifacts/subtask-plan.json`。**Phase 2**:经验检索 + 按需 deep research(默认关闭)。**Phase 3 v2**:CEO 心跳直接发现+派发(push),子任务走轻量 work graph(`org-coder`+`org-validator` 两节点)。**Phase 4**:父任务被拆分后让位给子任务(新状态 `decomposed`)、预算按步数均分、父子终态汇总(`settleParentTaskIfAllChildrenDone`)、同父子任务独立并发坑位(上限 3,不占公司级槽位)——真实回归当场撞出一个几乎必现的真缺陷(`markTaskDecomposed` 原本只认父任务还是 `queued`,但 task-scheduler 抢坑是毫秒级、`subtask-planning` 是数十秒的真实 LLM 调用,等它拆完时父任务几乎必然已经 `running`,接管必然失败)已修复并用真实数据验证;同父并发坑位也用真实数据确认生效(两条子任务真实同时 `running` 20+ 分钟)。**Phase 5**:看板加 `decomposed` 状态样式 + 子任务进度展示,父子树形复用已有通用逻辑,未改后端接口。回归过程中牵出一个独立缺陷——`org-validator` 对同一种 benchmark 契约判断不稳定(5 次里 1 次误把源码路径当 `--target` 判 `target_not_json`,反手倒退归因给 `subtask-planning`)——已定位根因(`decomposed_work` 轻量图当时只有一条前进边,没有失败边,validator 判 fail 后无路可退)并修复(补 `validate --fail--> impl` 退回边,复用引擎已验证过的 `backward_count` 双层硬顶 + `remediation_note` 反思闭环,新增 3 条单测),详见文末补跑记录 | +| [system-design/46-mandatory-planning-and-task-decomposition.md](./done/system-design/46-mandatory-planning-and-task-decomposition.md) | ✅ **已收口**(2026-09-07)。Phase 0-5 全部实现。**Phase 1**:新 agent `subtask-planning`,钩在 `enqueueTaskRun`(显式 opt-in),产物写共享 `artifacts/subtask-plan.json`。**Phase 2**:经验检索 + 按需 deep research(默认关闭)。**Phase 3 v2**:CEO 心跳直接发现+派发(push),子任务走轻量 work graph(`org-coder`+`org-validator` 两节点)。**Phase 4**:父任务被拆分后让位给子任务(新状态 `decomposed`)、预算按步数均分、父子终态汇总(`settleParentTaskIfAllChildrenDone`)、同父子任务独立并发坑位(上限 3,不占公司级槽位)——四项机制全部用真实数据验证过,包括最后补跑的父子终态汇总(两个真实子任务全部 `completed` 后父任务被正确自动结算成 `completed`)与第二次并发确认。过程中撞出并修复一个几乎必现的真缺陷(`markTaskDecomposed` 原本只认父任务还是 `queued`,但 task-scheduler 抢坑是毫秒级、`subtask-planning` 是数十秒的真实 LLM 调用,等它拆完时父任务几乎必然已经 `running`,接管必然失败)。**Phase 5**:看板加 `decomposed` 状态样式 + 子任务进度展示,父子树形复用已有通用逻辑,未改后端接口。回归过程中还牵出一个独立缺陷——`org-validator` 对同一种 benchmark 契约判断不稳定(5 次里 1 次误把源码路径当 `--target` 判 `target_not_json`,反手倒退归因给 `subtask-planning`)——已定位根因(`decomposed_work` 轻量图当时只有一条前进边,没有失败边,validator 判 fail 后无路可退)并修复(补 `validate --fail--> impl` 退回边,复用引擎已验证过的 `backward_count` 双层硬顶 + `remediation_note` 反思闭环,新增 3 条单测),详见文末补跑记录 | ## todo/(当前主线) diff --git a/docs/done/system-design/46-mandatory-planning-and-task-decomposition.md b/docs/done/system-design/46-mandatory-planning-and-task-decomposition.md index 6360a8c..65ab12e 100644 --- a/docs/done/system-design/46-mandatory-planning-and-task-decomposition.md +++ b/docs/done/system-design/46-mandatory-planning-and-task-decomposition.md @@ -1,6 +1,6 @@ # 46 · Planning 应作为每个任务的默认前置步骤,覆盖三类信息来源 -> **状态**: ✅ **已收口**(2026-09-06)。Phase 0-5 全部实现,核心机制均已用真实数据验证(父任务让位/预算均分/同父并发坑位/子任务真实跑通 org-coder→org-validator),父子终态汇总由单测严格覆盖但没等到真实链路触发那一刻。过程中牵出一个独立缺陷(`org-validator` 对同一种 benchmark 契约判断不稳定,5 次里 1 次误判)并已修复+补测试验证——`decomposed_work` 轻量图现在有了退回边,能对这类判断失误重试而不是永久卡死,详见文末补跑记录。四个关键决策已拍板。**Phase 0 已完成**(2026-09-01 真实回归验证):链路能收敛、44 号文档修复确认生效,发现的独立缺陷已拆到 [47 号文档](./47-itemized-subtask-materialization-goal-benchmark-fallback.md) 并修复。**Phase 1 代码已实现**(2026-09-02,见「Phase 1 实现记录」):新 agent `subtask-planning` + `enqueueTaskRun` 挂钩(收窄为显式 opt-in)+ 复用 R-9.3 任务级共享索引对接下游,单测覆盖,**但还没做真实端到端回归**(且过程中出过一次真实 CLI 子进程泄漏事故,已修复并加了测试环境防护,见该节)。**Phase 2 已实现且已做真实端到端回归(收窄版,2026-09-02,见「Phase 2 实现记录」)**:经验检索(新查询能力,扫已雇 agent 的 dream 沉淀)+ 按需 deep research(图外调用 org-hunt,默认关闭)。真实回归第一次就跑出一个真缺陷(关键词打分噪音压过信号,导致"经验库有答案"分支误触发)并已修复验证;两条真实任务的分解内容质量都好,但 deep research 分支目前更接近"多问一个角色的第二意见"而非真的做了外部检索(org-hunt 那次调用没有工具调用痕迹),如实记在实现记录里。"历史同类 goal 检索"这条来源本轮明确收窄未做。**Phase 3 走过一轮推翻重来(2026-09-02)**:v1("认领"pull 语义 + CAS)已实现并做过真实回归,但回归本身就暴露出"认领后没有触发源"的真问题,讨论后发现"认领"要解决的"多方竞争"场景根本不存在(只有 CEO 一人拍板要不要派)——**v2 改成 CEO 心跳直接发现+派发(push),删掉了 v1 的整套认领机制**,改为 CEO 判断节奏后调现成的 `/enqueue`,子任务默认走一张现造的轻量 work graph(`org-coder` 实现 + `org-validator` 验证两个节点,跳过公司完整 org graph 的规划仪式),效果不理想再升级成完整 org graph(见「Phase 3 v2」)。v1 设计和实现记录原样保留、标了废弃(留作决策过程的第一手记录,不是白做)。**v2 已做真实端到端回归**:真实 CEO 心跳确实发现并派发了子任务(顺手还修了一个真实的、影响面更大的 bug——两套心跳系统的自环调用一直缺内部令牌、暗中 401),递归防护、依赖阻塞都验证生效;`org-coder` 在没有 brd/prd/sdd 的轻量图里产出质量真实达标,但 `org-validator` 卡在硬依赖的 `acceptance.json`(只有 org-planner 会产出)上——**轻量图的执行没问题,验证这一半有真实的结构性缺口**,需要另外决定怎么补(见「Phase 3 v2」结尾三个方向)。**Phase 4(父任务让位 + 预算均分 + 父子终态汇总 + 同父并发坑位)已实现并做过真实端到端回归(2026-09-04,见「Phase 4 详细设计与实现记录」)**:真实回归第一次就撞出一个几乎必现的真缺陷——`markTaskDecomposed` 原本只认「父任务还是 `queued`」,但 task-scheduler 抢坑是毫秒级、`subtask-planning` 是数十秒的真实 LLM 调用,等它拆完回来时父任务几乎必然已经是 `running`,接管必然失败,而 `stopRun` 依然会把真实在跑的 org graph 取消掉,后果是父任务卡成 `cancelled`、物化好的子任务全变孤儿。已修复(接管条件放宽成"还没到终态、也没被接管过")并用真实公司复现+验证通过:父任务从真实 `running` 状态被正确接管为 `decomposed`,预算按步数精确均分(`100/5=20` 次调用、`5000000/5=1000000` token、`7200000/5=1440000` ms wallclock,真实落库数值核对过),依赖链驱动的子任务顺序生效,第一条子任务真实跑通了 `org-coder→org-validator` 全流程。**未在真实条件下跑到底**:驱动脚本的等待窗口到期后误杀了正在真实执行的第二条子任务(`org-coder` CLI 被中途 SIGTERM),该子任务因此被图引擎判成 `blocked`——这是回归方法论本身的时间预算问题,不是 Phase 4 代码的缺陷;父子终态汇总(`settleParentTaskIfAllChildrenDone`)与同父 3 并发坑位这两块在真实条件下没有跑到触发的那一刻,改由单测(`task-decomposition-phase4.test.js`)覆盖其 CAS/并发语义。**Phase 5(看板最小展示)已实现**:`decomposed` 状态样式 + 子任务进度 label,父子任务树形展示复用已有的通用 `parentTaskId` 分组逻辑,未改后端接口 +> **状态**: ✅ **已收口**(2026-09-07)。Phase 0-5 全部实现,Phase 4 全部四项机制(父任务让位/预算均分/父子终态汇总/同父并发坑位)均已用真实数据验证——父子终态汇总最后一块也已在 2026-09-07 补跑中拿到直接证据(见文末)。过程中牵出一个独立缺陷(`org-validator` 对同一种 benchmark 契约判断不稳定,5 次里 1 次误判)并已修复+补测试验证——`decomposed_work` 轻量图现在有了退回边,能对这类判断失误重试而不是永久卡死,详见文末补跑记录。四个关键决策已拍板。**Phase 0 已完成**(2026-09-01 真实回归验证):链路能收敛、44 号文档修复确认生效,发现的独立缺陷已拆到 [47 号文档](./47-itemized-subtask-materialization-goal-benchmark-fallback.md) 并修复。**Phase 1 代码已实现**(2026-09-02,见「Phase 1 实现记录」):新 agent `subtask-planning` + `enqueueTaskRun` 挂钩(收窄为显式 opt-in)+ 复用 R-9.3 任务级共享索引对接下游,单测覆盖,**但还没做真实端到端回归**(且过程中出过一次真实 CLI 子进程泄漏事故,已修复并加了测试环境防护,见该节)。**Phase 2 已实现且已做真实端到端回归(收窄版,2026-09-02,见「Phase 2 实现记录」)**:经验检索(新查询能力,扫已雇 agent 的 dream 沉淀)+ 按需 deep research(图外调用 org-hunt,默认关闭)。真实回归第一次就跑出一个真缺陷(关键词打分噪音压过信号,导致"经验库有答案"分支误触发)并已修复验证;两条真实任务的分解内容质量都好,但 deep research 分支目前更接近"多问一个角色的第二意见"而非真的做了外部检索(org-hunt 那次调用没有工具调用痕迹),如实记在实现记录里。"历史同类 goal 检索"这条来源本轮明确收窄未做。**Phase 3 走过一轮推翻重来(2026-09-02)**:v1("认领"pull 语义 + CAS)已实现并做过真实回归,但回归本身就暴露出"认领后没有触发源"的真问题,讨论后发现"认领"要解决的"多方竞争"场景根本不存在(只有 CEO 一人拍板要不要派)——**v2 改成 CEO 心跳直接发现+派发(push),删掉了 v1 的整套认领机制**,改为 CEO 判断节奏后调现成的 `/enqueue`,子任务默认走一张现造的轻量 work graph(`org-coder` 实现 + `org-validator` 验证两个节点,跳过公司完整 org graph 的规划仪式),效果不理想再升级成完整 org graph(见「Phase 3 v2」)。v1 设计和实现记录原样保留、标了废弃(留作决策过程的第一手记录,不是白做)。**v2 已做真实端到端回归**:真实 CEO 心跳确实发现并派发了子任务(顺手还修了一个真实的、影响面更大的 bug——两套心跳系统的自环调用一直缺内部令牌、暗中 401),递归防护、依赖阻塞都验证生效;`org-coder` 在没有 brd/prd/sdd 的轻量图里产出质量真实达标,但 `org-validator` 卡在硬依赖的 `acceptance.json`(只有 org-planner 会产出)上——**轻量图的执行没问题,验证这一半有真实的结构性缺口**,需要另外决定怎么补(见「Phase 3 v2」结尾三个方向)。**Phase 4(父任务让位 + 预算均分 + 父子终态汇总 + 同父并发坑位)已实现并做过真实端到端回归(2026-09-04,见「Phase 4 详细设计与实现记录」)**:真实回归第一次就撞出一个几乎必现的真缺陷——`markTaskDecomposed` 原本只认「父任务还是 `queued`」,但 task-scheduler 抢坑是毫秒级、`subtask-planning` 是数十秒的真实 LLM 调用,等它拆完回来时父任务几乎必然已经是 `running`,接管必然失败,而 `stopRun` 依然会把真实在跑的 org graph 取消掉,后果是父任务卡成 `cancelled`、物化好的子任务全变孤儿。已修复(接管条件放宽成"还没到终态、也没被接管过")并用真实公司复现+验证通过:父任务从真实 `running` 状态被正确接管为 `decomposed`,预算按步数精确均分(`100/5=20` 次调用、`5000000/5=1000000` token、`7200000/5=1440000` ms wallclock,真实落库数值核对过),依赖链驱动的子任务顺序生效,第一条子任务真实跑通了 `org-coder→org-validator` 全流程。**未在真实条件下跑到底**:驱动脚本的等待窗口到期后误杀了正在真实执行的第二条子任务(`org-coder` CLI 被中途 SIGTERM),该子任务因此被图引擎判成 `blocked`——这是回归方法论本身的时间预算问题,不是 Phase 4 代码的缺陷;父子终态汇总(`settleParentTaskIfAllChildrenDone`)与同父 3 并发坑位这两块在真实条件下没有跑到触发的那一刻,改由单测(`task-decomposition-phase4.test.js`)覆盖其 CAS/并发语义。**Phase 5(看板最小展示)已实现**:`decomposed` 状态样式 + 子任务进度 label,父子任务树形展示复用已有的通用 `parentTaskId` 分组逻辑,未改后端接口 > **日期**: 2026-09-01 > **触发场景**: 用户复盘 [43 号文档](./43-task-decomposition-granularity.md)(goal 分解粒度)时,追问"为什么本地和线上所有公司的任务看板都没有子任务分解"。核实后发现:不是巧合或配置遗漏,`acceptance_mode='itemized'` 在当前系统里**从未被真正触发并落库过一次**——追问引出了比 43 号文档更大的架构缺口:43 号文档只解决"验收要不要拆细",而用户认为**规划(把一件事拆成第一步/第二步/第三步)本身应该是每个任务默认必经的前置步骤,不是一个可选的、可以被判"不需要"的例外**。 > **格式对齐** `27-requirement.md`/[`43-task-decomposition-granularity.md`](./43-task-decomposition-granularity.md):原话照搬 + 结构化复述,现状调研另起一节。 @@ -550,3 +550,11 @@ v1 真实回归跑完,用户追问"认领后没有触发源,谁来触发"— **发现与修复过程中的一个插曲**:诊断到一半时发现 `system/agents/org-validator/{agent.md,tools.md}` 和 `work-graph-db.js` 的 `createDecomposedWorkGraph` 已经被**同一个共享工作目录里的另一个并行会话**修复过了——`agent.md` 补了一整节"你可能被裸调用"的规程说明(点名了另一条真实撞上同类问题的任务 `T-mto6lp1c`,证明这不是孤例),`createDecomposedWorkGraph` 补了 `{ from: 'validate', to: 'impl', condition: 'fail', edgeKind: 'backward' }` 这条边。核实这条边只用一行代码就接上了引擎里已经被 `graph-engine.test.js` 反复验证过的老机制(`backward_count` 双层硬顶 + `remediation_note` 自动喂给下一轮执行者),没有引入任何新的判断逻辑,是正确、低风险的修法。这条边此前完全没有测试覆盖,本次补了 3 条(`graph-engine.test.js`):图定义里边的形状对不对、"validate 判 fail → 真退回 impl → remediation_note 带给下一轮 → 第二轮 validate 判过 → run 收敛成 completed"整条链路(假 executor,零真实 API 成本)、连续判 fail 撞硬顶后不再无限重试。三条全过。 **这条修复只对新建的 decomposed_work 任务生效**——之前卡住的第 5 条子任务的 work graph 是修复前建的,edges 表里天生没有这条退回边,不会自动受益;真要在真实条件下走一遍"判 fail → 真退回 → 带反馈重跑 → 判过"的完整闭环,需要一条全新任务,本轮未做(机制已经用假 executor 验证得很扎实,真实条件下的完整验证留给下次touch这块代码时顺手做)。 + +### 最后一块补齐:父子终态汇总在真实条件下确认生效(2026-09-07) + +用一个全新 goal(三个互不依赖的独立字符串工具函数,刻意设计成容易并行)再跑一轮,拿到了此前一直没等到的直接证据:`capitalizeWords` 这条链被 `subtask-planning` 拆成两条子任务(实现 + 单元测试),两条子任务都真实 `completed` 后,**父任务被 `settleParentTaskIfAllChildrenDone` 正确自动结算成 `completed`**——父子终态汇总在真实链路上确认生效,不再只是单测层面的把握。同一批里 `reverseWordOrder` 的实现子任务与 `capitalizeWords` 的实现子任务一度真实同时 `running`(都是无依赖子任务),是继贪吃蛇那次 20+ 分钟并发之后,同父并发坑位的第二次真实确认。 + +**一个插曲,核实过与本次代码无关**:`reverseWordOrder` 那条链的两条子任务中途被同一个共享环境里另一个并行在跑的 agent(从 `memory/MEMORY.md` 被自动写入的记录看,是在排查"`execution_mode=manual` 的节点不会自动推进、别当成引擎卡死"这类问题时)取消掉了,顶层任务改由人工 `/next` 推完,走的不是 decomposed_work 路径。核实过 `decomposed_work` 子任务的 `execution_mode` 全程正确落成 `'auto'`(`materializeDecomposedSubtasks` 这段逻辑没有问题)——被取消的是顶层任务自己那条默认 `'manual'` 的普通 org graph run(因为这次 `POST /goals`/`dispatch` 没有显式传 `mode:'auto'`),跟本文档的任何机制无关,只是恰好撞上了同一批任务被另一个 agent 同时处理。 + +至此,Phase 4 四项机制(父任务让位、预算均分、父子终态汇总、同父并发坑位)以及顺带修复的 org-validator 退回边,全部在真实条件下拿到过至少一次直接证据,不再只是单测覆盖。测试公司 `p2verify0902` 里此前两次因脚本 bug 失败的回归数据(`G-mtn5q2r7-786b`、`G-mtn5tvih-bed4`)已通过正式归档接口清理(不是裸删库),本轮新数据(goal `G-mtrad3iw-5af8`)保留作为最新证据。