Commit 5c7e5ce8e170e843ed4f42050a5469175b217847
1 parent
b5bd5e71
docs(43号): goal 分解粒度需求 + 方案定案 + 技术实现计划
回应"org-planner 出 brd/prd/sdd 后,任务看板能不能展示成 task/sub-task 树,coder-validator 按清单逐条开发验收"。原话照搬 + 结构化复述 + 现状调研(parent_task_id 只服务于 Agent Chat 派单流程、task-planning 人设明确拒绝按检查项拆 task、org-planner 没有建任务工具)。 三轮讨论定案:goal→task 流水线自建父子机制、先只拆验收(开发仍整体 完成)、要不要拆交给 task-planning 判断、任一子任务 fail 父任务即 fail、子任务复用 tasks.status 状态语义。 技术实现计划 Phase 0-4 逐条核实代码形态,含两处订正(org-validator/ coder-validator 是不同 agent;org-planner 产出的验收清单是 acceptance.md 不是 acceptance.json)和一个待验证风险(acceptance.md 在真实回归里 从未被用上,Phase 2 落地前需先确认可靠性)。尚未开工。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U7xYyvv3pzuV9diMVUH5QL
Showing
2 changed files
with
139 additions
and
0 deletions
docs/README.md
| @@ -60,6 +60,7 @@ Graph Agent 架构重构(27 系列)。**已完成的阶段文档已移入 `d | @@ -60,6 +60,7 @@ Graph Agent 架构重构(27 系列)。**已完成的阶段文档已移入 `d | ||
| 60 | | [37-org-graph-department-scoping.md](./todo/system-design/37-org-graph-department-scoping.md) | 📝 **设计讨论,调用点扫描已完成,尚未立项实现**。现状 org graph 按 `company_id` 单例(`27-P2` 标题原文即"公司级"),塞不下 HR/财务/市场这类跟"交付流水线"无关的公司常设职能——`system/agents/hr/`("招·留·管·退")本体已存在却从没被装进任何图,全靠 fire-and-forget chat 招聘、无图执行审计轨迹。提议把 org graph 作用域从 `company_id` 升级为 `(company_id, department_id)`,一家公司可装配多张部门图,每张仍保持人工固定/慢变/可审计。全仓库调用点扫描结论:改造面是最初估算的 4 倍——真正的单点真相在 `work-graph-db.js:readDefGraph` 的裸 SQL 不变式(不在服务层),还牵涉两个易混淆服务文件间必须字节级一致的重复唯一索引、独立的 `graph-seed-service.js` 对账子系统、`company-hire-org-layer.test.js` 专属测试、`orggraph-planning`/`task-planning` 两份 agent 人设文档的自我认知改写 | | 60 | | [37-org-graph-department-scoping.md](./todo/system-design/37-org-graph-department-scoping.md) | 📝 **设计讨论,调用点扫描已完成,尚未立项实现**。现状 org graph 按 `company_id` 单例(`27-P2` 标题原文即"公司级"),塞不下 HR/财务/市场这类跟"交付流水线"无关的公司常设职能——`system/agents/hr/`("招·留·管·退")本体已存在却从没被装进任何图,全靠 fire-and-forget chat 招聘、无图执行审计轨迹。提议把 org graph 作用域从 `company_id` 升级为 `(company_id, department_id)`,一家公司可装配多张部门图,每张仍保持人工固定/慢变/可审计。全仓库调用点扫描结论:改造面是最初估算的 4 倍——真正的单点真相在 `work-graph-db.js:readDefGraph` 的裸 SQL 不变式(不在服务层),还牵涉两个易混淆服务文件间必须字节级一致的重复唯一索引、独立的 `graph-seed-service.js` 对账子系统、`company-hire-org-layer.test.js` 专属测试、`orggraph-planning`/`task-planning` 两份 agent 人设文档的自我认知改写 | |
| 61 | | [36-prd-agent-methodology-training-feasibility.md](./todo/system-design/36-prd-agent-methodology-training-feasibility.md) | 📝 **调研 + 阶段一/二均已完成**。回应"落地页太单薄是不是该用 Innovator 先训练专业 agent、再用 Dream 持续迭代"——认同方向。**阶段一**:`graph-engine.js` 结算节点后把 `success`/`fail:<reason>` 写进本体 `memory.md`(此前只有人类对话路径会写,Dream 天天空转)。**阶段二**:新建独立试验节点 `prd-methodology-trial` 走真实 Hunt→Digest→Evolve,2 轮收敛(96/97 分,真实基线 50 分),三个真实历史项目反推验证方法论有效;过程中连带修复同一个 2026-08-16 改名批次遗留的 5 处 `innovator`→`org-innovator` 死链(后端两处硬编码、前端"重新训练"按钮、`/api/agent/list` 展示 id 来源的四个 `config.json`),以及 `AgentScaffold` 默认模板一处裸相对路径缺陷。结论:FDE 对方法论类角色确实管用,但收敛速度/验收严谨度依赖任务书显式写明的自纠正要求,非免人工黑盒。环节 3(训练产物 → 雇佣本体转换)尚未开工 | | 61 | | [36-prd-agent-methodology-training-feasibility.md](./todo/system-design/36-prd-agent-methodology-training-feasibility.md) | 📝 **调研 + 阶段一/二均已完成**。回应"落地页太单薄是不是该用 Innovator 先训练专业 agent、再用 Dream 持续迭代"——认同方向。**阶段一**:`graph-engine.js` 结算节点后把 `success`/`fail:<reason>` 写进本体 `memory.md`(此前只有人类对话路径会写,Dream 天天空转)。**阶段二**:新建独立试验节点 `prd-methodology-trial` 走真实 Hunt→Digest→Evolve,2 轮收敛(96/97 分,真实基线 50 分),三个真实历史项目反推验证方法论有效;过程中连带修复同一个 2026-08-16 改名批次遗留的 5 处 `innovator`→`org-innovator` 死链(后端两处硬编码、前端"重新训练"按钮、`/api/agent/list` 展示 id 来源的四个 `config.json`),以及 `AgentScaffold` 默认模板一处裸相对路径缺陷。结论:FDE 对方法论类角色确实管用,但收敛速度/验收严谨度依赖任务书显式写明的自纠正要求,非免人工黑盒。环节 3(训练产物 → 雇佣本体转换)尚未开工 | |
| 62 | | [34-validator-scored-without-real-deliverable.md](./todo/system-design/34-validator-scored-without-real-deliverable.md) | 📝 **调研记录,checklist 已查完**。最初以为 `org-coder-impl` 从未产出任何 HTML/CSS,后来发现真实网站其实存在于 `graph_files` 索引不覆盖的「项目根」目录(已顺手修:控制台「产物」面板现在会展示项目根)。追加查清 validator 有没有真的做浏览器级检查——中途自我订正一次:不是"没工具做不到"(`bash` 能走到仓库自带的 Playwright,另一条对照任务证明可行),是**没人教它这么做**;抽查另外两个项目根后发现**验证严谨度完全不稳定**(同类任务有的做了真实 Playwright 级验证、有的只做静态正则、有的没验证就被取消),根因很可能是新招聘的 `unit-tester` 本体撞上了 [32 号文档](./todo/system-design/32-hire-body-fill-reliability.md) 那类"装配没填充完"的真实样本,不是平台工具限制 | | 62 | | [34-validator-scored-without-real-deliverable.md](./todo/system-design/34-validator-scored-without-real-deliverable.md) | 📝 **调研记录,checklist 已查完**。最初以为 `org-coder-impl` 从未产出任何 HTML/CSS,后来发现真实网站其实存在于 `graph_files` 索引不覆盖的「项目根」目录(已顺手修:控制台「产物」面板现在会展示项目根)。追加查清 validator 有没有真的做浏览器级检查——中途自我订正一次:不是"没工具做不到"(`bash` 能走到仓库自带的 Playwright,另一条对照任务证明可行),是**没人教它这么做**;抽查另外两个项目根后发现**验证严谨度完全不稳定**(同类任务有的做了真实 Playwright 级验证、有的只做静态正则、有的没验证就被取消),根因很可能是新招聘的 `unit-tester` 本体撞上了 [32 号文档](./todo/system-design/32-hire-body-fill-reliability.md) 那类"装配没填充完"的真实样本,不是平台工具限制 | |
| 63 | +| [43-task-decomposition-granularity.md](./todo/system-design/43-task-decomposition-granularity.md) | 📝 **需求 + 方案定案 + 技术实现计划(5 个 Phase)已写完,尚未开工**。回应"org-planner 出 brd/prd/sdd 后,任务看板能不能展示成 task/sub-task 树,coder-validator 按清单逐条开发验收"。方案:goal→task 流水线自建父子机制、先只拆验收(开发仍整体完成)、`tasks.acceptance_mode` 由 task-planning 判断、子任务复用 `tasks.status` 既有状态语义、任一子任务 fail 父任务即 fail。**Phase 0-4** 逐条核实了代码形态:`createTask()`/`parent_task_id` 迁移模板、task-planning "硬规则 5"需要开例外让 LLM 多写一个字段、`org-planner` 产出的验收清单其实是 `acceptance.md` 不是 `acceptance.json`(且⚠️真实回归里从未被用上,落地前需先验证可靠性)、`coder-validator`(不是 org-validator,文档订正过一次)的 `checks[]` 目前没有任何服务端代码解析、看板树形渲染有 `FileNode.vue` 现成模板可抄。建议实施顺序 Phase 0→1→4→2→3 | | ||
| 63 | 64 | ||
| 64 | ## todo/future/(暂缓,非当前重心) | 65 | ## todo/future/(暂缓,非当前重心) |
| 65 | 66 |
docs/todo/system-design/43-task-decomposition-granularity.md
0 → 100644
| 1 | +# 43 · Goal 分解粒度:规划产出该长成文件,还是长成 task/subtask 树 | ||
| 2 | + | ||
| 3 | +> **状态**: 📝 需求 + 现状调研,尚未设计、未实现 | ||
| 4 | +> **日期**: 2026-08-31 | ||
| 5 | +> **触发场景**: snakegame-co 公司,goal `G-mtfh23mu-bd63`("HTML 贪吃蛇游戏"),task `T-mtfh2kuf-7c31`。 | ||
| 6 | +> 该任务当天被 `missing_required_input` 死循环卡住(根因与修复见 [33 号文档](../../done/system-design/33-needs-gate-role-filter-bug.md) 的复发一例, | ||
| 7 | +> `tools.md` 范例与 `work-graph-db.js` 引擎层已同日修复),排查过程中用户提出了本篇的需求。 | ||
| 8 | +> **格式对齐** `27-requirement.md`:原话照搬 + 结构化复述,现状调研另起一节。 | ||
| 9 | + | ||
| 10 | +--- | ||
| 11 | + | ||
| 12 | +## 原始需求(用户原话,一字不改) | ||
| 13 | + | ||
| 14 | +> 就这个任务,我讲讲我理想的状态,应该是 org planner 完成了brd prd sdd 后,在 task 任务看板应该能看到规划出来的 todo list 作为这个 html 贪吃蛇游戏 goal 的 task 和 sub task 展示出来,然后每一个 org coder 都是按照这个 task todo list 在逐个的开发完成,然后 org validator 应该是针对 task todo list 在逐个验收,这个现在是不是实现不了? | ||
| 15 | + | ||
| 16 | +--- | ||
| 17 | + | ||
| 18 | +## 结构化复述 | ||
| 19 | + | ||
| 20 | +用户设想的理想流程,拆成四步: | ||
| 21 | + | ||
| 22 | +1. **规划阶段**:org-planner 完成 brd/prd/sdd 之后,不只是产出文档,还应该把这份规划**分解成一份 todo 清单**。 | ||
| 23 | +2. **展示阶段**:这份 todo 清单应该以 **task 和 sub-task** 的形态出现在任务看板上,挂在"HTML 贪吃蛇游戏"这个 goal 下面(例子:方向键控制、吃食物加分、碰撞结束、重新开始——即当前 `acceptance.json` 里的 A.1-A.5)。 | ||
| 24 | +3. **开发阶段**:org-coder 不是一次性对着一大段任务描述写完整个交付物,而是**按 todo 清单逐条**开发。 | ||
| 25 | +4. **验收阶段**:org-validator 也不是一次性给整个交付物判总分,而是**按 todo 清单逐条**验收。 | ||
| 26 | + | ||
| 27 | +用户明确问:**现状是不是做不到这个?** | ||
| 28 | + | ||
| 29 | +--- | ||
| 30 | + | ||
| 31 | +## 现状调研结论(本次会话核实,非最终设计) | ||
| 32 | + | ||
| 33 | +结论:**部分可以,"做不到"的那部分是当前 agent 设计上的主动选择,不是漏做的功能**。四层现状分别是: | ||
| 34 | + | ||
| 35 | +### 1. `tasks.parent_task_id`——字段在,但服务的是另一条流水线 | ||
| 36 | + | ||
| 37 | +`tasks` 表(`server/services/work-graph-db.js`)确实有 `parent_task_id` 列,也确实有代码在读写它——但那是 **LemonBoss Agent Chat 的人工派单流程**(`server/routes/agent-chat.js` + `task-service.js` 建任务树),跟本篇讨论的 goal → task → org-graph/work-graph 这条流水线是两套独立机制。 | ||
| 38 | + | ||
| 39 | +本篇关心的这条流水线里,真正负责"从 goal 生成 task 行"的函数是 `work-graph-db.js` 的 `createTask({goalId, companyId, seq, title, description, executionMode, dependsOn, priority, budgetJson, reportTo, createdBy})`——**这个函数签名里根本没有 `parentTaskId` 参数**。也就是说,子任务对这条流水线而言是**结构性够不着**,不是"字段有、没人填"。 | ||
| 40 | + | ||
| 41 | +### 2. task-planning 阶段本身有能力拆多任务,但拆分依据不是"检查项" | ||
| 42 | + | ||
| 43 | +真正把 goal 拆成 task 的阶段是 `task-planning`(`server/services/task-planning.js` + `system/agents/task-planning/`,落库调用点在 `server/routes/company.js:1577 insertTasksForGoal`)。这一步**确实能一次拆出多条 task**(已有测试验证过 2 条以上的场景)。 | ||
| 44 | + | ||
| 45 | +snakegame-co 这次只拆出 1 条 task,不是能力限制,是 **`system/agents/task-planning/agent.md` 第二步的明确设计判断**:拆分依据是"交付物/验收边界",**不是"工作阶段"**。原文点名"①调研②设计③开发④测试⑤上线"这种按阶段拆是"最常见也最致命的错法"。按这份人设的判断,方向键/得分/碰撞/重开这四条,是**同一个交付物的验收清单**(正是最终 `acceptance.json` 里一起被同一份 Playwright 脚本验证的 A.1-A.5),不是四个可以独立排期验收的 task——agent 设计上就会拒绝把它们拆成四条 task。该 agent 人设还硬顶单 goal ≤ 8 条 task,整体偏"合并"不偏"细分"。 | ||
| 46 | + | ||
| 47 | +### 3. org-planner 没有"建任务"这个工具 | ||
| 48 | + | ||
| 49 | +org-planner 在跑的时候(`system/agents/org-planner/tools.md`)能力边界是:调研 → 阶段流转 → 写 brd/prd/sdd/acceptance.md 这几份**文件** → 向 CEO 汇报。**没有任何一个工具允许它创建新的 task 行**(org-coder / org-validator 同样没有)。规划阶段的产出,结构上只能落成文档,附着在它所属的那一条已经固定的 task 上,没法在跑的过程中反过来生出新的、可独立调度的子任务。 | ||
| 50 | + | ||
| 51 | +### 4. 看板 UI 没有树形渲染 | ||
| 52 | + | ||
| 53 | +`web/src/views/TaskBoard.vue`、`web/src/components/graph-console/GoalTaskPane.vue` 目前都没有父子任务的渲染逻辑——即便前三层都打通、数据库里真的出现了带 `parentTaskId` 的行,看板现在也画不出树形结构,只会当成平铺列表处理(或者干脆不显示子任务)。 | ||
| 54 | + | ||
| 55 | +--- | ||
| 56 | + | ||
| 57 | +## 设计决策(2026-08-31 定案,三选一各选完) | ||
| 58 | + | ||
| 59 | +| 问题 | 决定 | 理由 | | ||
| 60 | +|------|------|------| | ||
| 61 | +| 子任务挂在哪套机制上 | **goal → task 流水线里新建一套独立父子机制**(不复用 Agent Chat 的 `parent_task_id`) | 后者是为「人工派单、多轮对话」设计的语义,跟 org-graph 自动执行的生命周期(谁创建、何时终结)对不上,硬凑容易埋雷 | | ||
| 62 | +| 子任务要不要独立开发+验收循环 | **先只拆验收,开发仍整体完成**——org-coder 一次性写完整个交付物,验收侧改成按子任务(验收条目)逐条判,而不是给总分 | 改动小得多,且先解决「验收颗粒度太粗」这个更痛的点;独立开发循环(每个子任务各起一个 work-graph run)留作后续再评估 | | ||
| 63 | +| 什么粒度的 goal 该拆 | **由 task-planning agent 自己判断**,不写死规则 | 跟它现在「要不要拆多个 task」的判断逻辑同源,交给同一套"交付物/验收边界"标准,不额外发明一套阈值规则 | | ||
| 64 | + | ||
| 65 | +由这三条决定组合出的实现方向:**task-planning 判断"值不值得走细粒度验收"是一个粗粒度的开关,真正的子任务清单在 org-planner 写完 acceptance.json 之后才生成**——因为验收条目本身就是规划阶段的产出,task-planning 跑的时候 brd/prd/sdd 还不存在,没法预先知道要拆成哪几条。这意味着"判断要不要拆"和"生成子任务"是两个时间点、两个步骤: | ||
| 66 | + | ||
| 67 | +1. **task-planning(goal 创建时)**:新增一个判断维度——这个 task 的验收后续要不要走"逐条子任务"模式,写一个标记(例如 task 行上加 `acceptance_mode: 'holistic' | 'itemized'`,或等价字段),不生成任何子任务行。 | ||
| 68 | +2. **org-planner 收尾(acceptance 产物写完之后,org-graph 流程内新增一步)**:如果上一步标记是 `itemized`,读验收条目,逐条 `createTask({parentTaskId, ...})` 生成子任务行,挂在同一个 goal 下。 | ||
| 69 | +3. **`coder-validator`(work-graph 内既有节点,就是本 session 全程调试的那个 agent)**:判断逻辑从"给整个 task 一个总分"改成"遍历子任务逐条判",每条子任务各自 success/fail,父任务的终态由子任务汇总(全 success → success,否则看具体子任务)。 | ||
| 70 | +4. **看板 UI**:`TaskBoard.vue` / `GoalTaskPane.vue` 加父子任务树形渲染,只读展示,不涉及交互改动。 | ||
| 71 | + | ||
| 72 | +## 实现细节决策(2026-08-31 定案) | ||
| 73 | + | ||
| 74 | +| 问题 | 决定 | 理由 | | ||
| 75 | +|------|------|------| | ||
| 76 | +| 标记字段怎么设计 | **`tasks` 表加 `acceptance_mode` 字段**,取值 `'holistic' \| 'itemized'`,命名风格对齐既有 `execution_mode`(manual/auto),由 task-planning 生成 task 行时一并写入 | 不额外发明隐式推导规则,创建时就能在库里直接看到这条 task 走哪种验收模式,调试/展示都直观 | | ||
| 77 | +| 部分子任务失败时父任务终态 | **必须全部子任务 success,父任务才 success**;任一子任务 fail → 父任务 fail | 跟当前"一次性给总分、不合格就是不合格"的严谨程度保持一致,也呼应 [34 号文档](./34-validator-scored-without-real-deliverable.md) 关于验证不能打折的教训;`optional` 子验收项留作后续需要时再加,先不预留这层复杂度 | | ||
| 78 | +| 子任务要不要复用现成的状态语义 | **复用**(pending/ready/running/success/fail/blocked 这套状态词汇) | 直接复用能白拿状态流转、看板渲染的既有约定,不用另起一套并行的状态语义 | | ||
| 79 | + | ||
| 80 | +> **落地时的订正**(技术设计阶段核实后发现):上一行"复用现成状态机"字面上写的是 `graph_run_nodes` 那套,但子任务本质是 `tasks` 表的行(带 `parent_task_id`),不是某个 work-graph run 内部的节点实例——它没有自己独立的 run。所以真正落地时复用的是 **`tasks.status` 这套既有枚举**(`queued/running/blocked/completed/failed/cancelled`),只是**沿用同一套状态词汇的精神**(有限状态、终态幂等、`settleNode`/`settleTaskFromRun` 那一类条件更新闸门),不是字面上去 `graph_run_nodes` 表插行。见下方技术实现计划 Phase 3。 | ||
| 81 | + | ||
| 82 | +> **另一处订正**:上面第 3 步原来写的是"org-validator",但技术设计阶段查证后发现 **`org-validator` 和 `coder-validator` 是两个不同目录、不同职责的独立 agent**——`org-validator` 是 org-graph 顶层节点(整体验收),`coder-validator` 是 org-coder 这一层 work-graph 内部的节点(就是本 session 全程调试的那个,`work-validator/v1` 输出格式)。真正产出逐项验收证据、需要按子任务逐条判的是 **`coder-validator`**,已在上面订正。 | ||
| 83 | + | ||
| 84 | +至此,43 号文档的方案层面已经全部定案。下面是核实过具体代码形态后的技术实现计划。 | ||
| 85 | + | ||
| 86 | +--- | ||
| 87 | + | ||
| 88 | +## 技术实现计划(2026-08-31,代码形态已核实,未开工) | ||
| 89 | + | ||
| 90 | +### Phase 0 · Schema | ||
| 91 | + | ||
| 92 | +- `tasks` 表加 `acceptance_mode` 列,`CHECK (acceptance_mode IN ('holistic','itemized')) DEFAULT 'holistic'`——语法上照抄 `execution_mode` 已有的 CHECK 写法(`work-graph-db.js:533`),迁移方式照抄 `parent_task_id` 自己当年落地时用的 `hasColumn` 判断 + `ALTER TABLE` 兜底那一段(`work-graph-db.js:626-627`),同一个文件里已有两份现成模板可抄,不用发明新的迁移写法。 | ||
| 93 | +- `createTask({...})` 签名(`work-graph-db.js:1861-1873`)加 `parentTaskId`、`acceptanceMode` 两个参数,INSERT 列表(`work-graph-db.js:1902-1907`)跟着加。`parent_task_id` 列本身早就存在(是 Agent Chat 那条派单流程在用),这里只是**第一次让 goal→task 流水线自己也写这一列**——顺手确认一下现有读它的 `task-service.js:66-81` 那段任务树构建逻辑,会不会因为多了一类新来源的父子行而产生非预期的合并/展示(大概率不会,因为按 `company_id`/`goalId` 天然分域,但落地前应该跑一次它的既有测试)。 | ||
| 94 | +- 守卫测试:图流水线创建的顶层 task(`insertTasksForGoal` 路径)`parent_task_id` 仍是 `NULL`;子任务的 `parent_task_id` 非空且指向父任务、`acceptance_mode` 恒为 `'holistic'`(子任务不允许再递归拆一层)。 | ||
| 95 | + | ||
| 96 | +### Phase 1 · task-planning 判断 `acceptance_mode` | ||
| 97 | + | ||
| 98 | +`task-planning` 目前是纯"回复 JSON 代码块"模式(`system/agents/task-planning/tools.md:5`),产出 4 字段 `[{seq, title, description, depends_on}]`(`agent.md:120-142`),而且**硬规则 5**(`agent.md:10`)明确禁止 LLM 多写字段——"服务端生成,你写了会被当成脏字段打回",`mode`/`priority`/`budget` 这些运营字段都是 `company.js:1396-1429 buildTaskPlans()` 在服务端按 goal 级默认值统一注入的(`company.js:1421-1423`),不是 LLM 决定的。 | ||
| 99 | + | ||
| 100 | +`acceptance_mode` 要不要拆本质上是一次语义判断(跟"要不要拆多个 task"用的是同一种判断力,这正是当初选"由 agent 自己判断、不写死规则"的理由),**没法**像 `mode`/`priority`/`budget` 那样简单地由服务端注入默认值——所以这里必须**显式在硬规则 5 上开一个例外**: | ||
| 101 | + | ||
| 102 | +- `agent.md` 的 JSON schema 从 4 字段扩到 5 字段,加 `acceptance_mode`,并在硬规则 5 旁边补一句明确的例外说明(为什么这一个字段跟其它运营字段不同,避免以后被"这些字段都是服务端生成"的惯例带偏、被误当脏字段清掉)。 | ||
| 103 | +- `buildTaskPlans()`(`company.js:1396-1429`)改成**透传** LLM 给的 `acceptance_mode`,而不是像其它字段那样用服务端默认值覆盖;LLM 没给这个字段时兜底 `'holistic'`(保守,不引入新行为,除非规划阶段明确判断要拆)。 | ||
| 104 | + | ||
| 105 | +### Phase 2 · org-planner 收尾生成子任务(⚠️ 有一个真实风险要先处理) | ||
| 106 | + | ||
| 107 | +org-planner 的 4 阶段 FSM(`system/agents/org-planner/tools.md:19-23`,`node bin/lemon.js task transition --phase {plan|execute|verify}`)产出的验收清单叫 **`acceptance.md`**(不是 `.json`)——Markdown 表格 `| # | 验收项 | 判定方式 | pass 条件 |`(`tools.md:44-50`),一行一条验收项,是子任务清单最自然的数据源。这**不是**同名的 R-19-B `acceptance.json` 契约(`goal-contract.js:76` 定义的 `benchmark|test_data|test_script` 三段式,由另外三个独立的 `goal-benchmark`/`goal-test-data`/`goal-test-script` 节点产出)——两者名字像、来源和用途完全不同,写代码时一定要认清楚读的是哪一份。 | ||
| 108 | + | ||
| 109 | +**⚠️ 已知风险,动工前必须先确认**:本 session 全程调试的 snakegame-co 这条真实任务,`acceptance.md` 和 `acceptance.json` **实际上都没有被真正当成验收依据用**——`coder-validator` 最终判定用的是自己临时写的一套 Playwright 测试(A.1-A.5),`goal-contract.js` 那份 `acceptance.json` 甚至报了 `note:"goal-contract.js cannot parse index.html as JSON...treat as no task-level contract"`,被当场判定"这个任务没有 task 级契约"直接跳过。如果子任务清单要建在 `acceptance.md` 之上,得先跑一次真实回归确认它确实会被稳定产出、格式跟文档描述一致——不能假设它已经可靠,这跟 33 号文档"建立在一个从来没人真正产出过的 `kind='log'` 之上"是同一类风险,值得先花一次真跑单独验证,而不是直接在上面盖楼。 | ||
| 110 | + | ||
| 111 | +如果验证通过,新增步骤:org-planner 的 `verify` 阶段落盘 `acceptance.md` 之后,插入一步"物化子任务"——仅当父任务 `acceptance_mode==='itemized'` 时,逐行读表格,为每一条验收项调用 `createTask({parentTaskId: 当前 task.id, acceptanceMode:'holistic', title: 该行"验收项"文本, description: 该行"判定方式"+"pass 条件", ...})`。 | ||
| 112 | + | ||
| 113 | +两个待确认的实现细节: | ||
| 114 | + | ||
| 115 | +- 这一步该是给 org-planner 加一个新工具(让它自己触发"物化子任务"),还是挂在服务端某个 hook 上(`verify` 阶段落盘后自动触发,agent 无感)?倾向后者——子任务生成是纯数据搬运,不需要占用一次 agent 调用去决定"要不要生成"(`acceptance_mode` 这个语义判断已经在 Phase 1 做完了),机械地转换 Markdown 表格到 task 行不需要 LLM 参与。 | ||
| 116 | +- 本次调研**没能确认** org-planner"完成→进入 org-coder"具体由哪个信号触发(`verify` transition 本身,还是 `tools.md:59-65` 那个额外的 `task/report` 调用)——插入新步骤前必须先查清楚,避免插错时机打断现有的阶段流转。 | ||
| 117 | + | ||
| 118 | +### Phase 3 · coder-validator 改成逐条判 + 回写子任务状态 | ||
| 119 | + | ||
| 120 | +关键发现:`coder-validator` 现在产出的 `checks[]`/`verdict` 结构化 JSON(就是本 session 里 `attempt-2.json` 那种形状),**目前没有任何服务端代码解析它**——`graph-engine.js` 判定这个节点成功与否只看 executor 返回的顶层 `status` 字段,`checks[]` 纯粹是给人看的审计文本,`goal-contract.js` 走的是完全独立的另一条 CLI 路径(自己生成 `verdict_id`),跟 `coder-validator` 的输出没有关系。 | ||
| 121 | + | ||
| 122 | +所以"逐条判"要真正影响子任务状态,**不能只是把 agent 提示词写得更细**——必须新增一个真实的工具调用:`coder-validator` 每判完一条验收项,调用一次新工具(例如 `report-subtask-result`),带上子任务 id + success/fail,服务端据此走一次 `tasks` 表的条件更新(复用 `settleTaskFromRun` 同款的"终态幂等闸门"思路:已经是终态的子任务不能被覆盖)。这跟本 repo 一贯的做法一致——状态改变走真实工具调用,不解析自由文本 JSON(`checks[]` 格式在 `org-validator`/`coder-validator`/`planner-validator`/`testdata-validator`/`benchmark-validator` 五个 validator 之间只是"约定俗成、没有强制"的 `work-validator/v1`,不是哪里都强制校验的 schema,解析它不安全)。 | ||
| 123 | + | ||
| 124 | +父任务终态:全部子任务 `completed` → 父任务按现有 `settleNode` 逻辑判 success;任一子任务 `failed` → 父任务 fail(Phase 0 就已经决定)。 | ||
| 125 | + | ||
| 126 | +### Phase 4 · 看板树形渲染 | ||
| 127 | + | ||
| 128 | +- `web/src/components/FileNode.vue` 是现成的自递归 `<script setup>` 组件模板(`v-for="child in node.children"` + `depth*14+6` 缩进),照这个结构写一个 `TaskNode.vue`,不用发明新模式。 | ||
| 129 | +- `GoalTaskPane.vue:78-131` 现在是纯平铺 `<ul class="tasks"><li v-for="t in g.tasks || []">`,改成先按 `parentTaskId` 把 `g.tasks` 分组建成树,再用 `TaskNode` 递归渲染。`TaskBoard.vue` 本身不用改——它是纯外壳,全权委托给 `GoalTaskPane.vue`(`TaskBoard.vue:23-32`)。 | ||
| 130 | +- `taskView()`(`company.js:994-1031`,`GET /:companyId/goals?withTasks=1` 等多个路由共用的唯一整形函数)要把 `parent_task_id`、`acceptance_mode` 加进输出字段列表——目前两个字段都完全没有出现在响应里,包括未使用的形式都没有。 | ||
| 131 | + | ||
| 132 | +### 建议的实施顺序 | ||
| 133 | + | ||
| 134 | +**Phase 0 → 1 → 4 → 2 → 3。** | ||
| 135 | + | ||
| 136 | +Phase 4(看板渲染)提前到 Phase 2/3 之前:先用手工插入的测试数据验证树形展示对不对,把"看得见"和"能自动生成"两件事解耦,避免一次性大集成、出问题不知道是生成的问题还是展示的问题。 | ||
| 137 | + | ||
| 138 | +Phase 2 排在 Phase 3 之前,且内部先做"acceptance.md 是否真的可靠"这次独立验证——这是唯一一个建在未经证实的既有产物之上的环节,值得单独花一次真跑确认,再决定要不要照原计划往下建。 |