From 9c8be28def6cfdba86a79e49bfcc04bcadc45145 Mon Sep 17 00:00:00 2001 From: yibo Date: Sat, 15 Aug 2026 17:24:48 +0800 Subject: [PATCH] docs(graph-agent): 验收产物改回 goal- 前缀,并确立 goal / task / okr 三者的基数区分 --- docs/todo/system-design/27-e2e-task-execution-flow.md | 17 ++++++++--------- docs/todo/system-design/27-example-dev-company-walkthrough.md | 13 ++++++------- docs/todo/system-design/27-graph-agent-architecture.md | 1 + docs/todo/system-design/27-naming-conventions.md | 35 ++++++++++++++++++++++------------- docs/todo/system-design/27-p3-p4-work-graph-console.md | 1 + docs/todo/system-design/27-requirement.md | 25 ++++++++++++++++++++++--- 6 files changed, 60 insertions(+), 32 deletions(-) diff --git a/docs/todo/system-design/27-e2e-task-execution-flow.md b/docs/todo/system-design/27-e2e-task-execution-flow.md index b7f166f..bd9d021 100644 --- a/docs/todo/system-design/27-e2e-task-execution-flow.md +++ b/docs/todo/system-design/27-e2e-task-execution-flow.md @@ -86,7 +86,7 @@ P2 已经设计了:`system/org-graph-templates/{dev,content,ops}.json` 模板å ❌ **缺口**:`from`/`to` 都必须是已存在的 agent 目录,**只支持 agent → agent 派发,不支持「用户 → 公司」**。你的流程第 3 步需要一个新入口:用户把任务给公司,由公司决定哪个 org node 先接手。 -⚠️ **另一处**:27 号文档 `work_graphs.goal_task_id` 这个单字段不够用。定位一个 OKR 节点需要 `(companyId, okrNodeId)`(OKR 树 per-company 存储,节点 ID 是点分层级)。建议拆成 `okr_node_id` + `task_id` 两个字段。⚠️ 另见 [27-NAMING](./27-naming-conventions.md) §六:OKR 体系当前在代码里叫 `goal`(`goals.js` / `G-001.1.1` / `data/companies/{cid}/goals/`),应正名为 `okr` / `O-001.1.1`。 +⚠️ **另一处**:27 号文档 `work_graphs.goal_task_id` 这个单字段不够用。定位一个 OKR 节点需要 `(companyId, okrNodeId)`(OKR 树 per-company 存储,节点 ID 是点分层级)。建议拆成 `goal_id`(一次人类需求,验收边界)+ `task_id`(执行单元,一个 goal 多个)+ `okr_node_id`(长周期度量归属)三个字段,三者基数不同不能混用,见 [27-NAMING](./27-naming-conventions.md) §四。⚠️ 另见 [27-NAMING](./27-naming-conventions.md) §六:OKR 体系当前在代码里叫 `goal`(`goals.js` / `G-001.1.1` / `data/companies/{cid}/goals/`),应正名为 `okr` / `O-001.1.1`。 ### 阶段 4 · 第一个 org node(planner)调 planning-work-graph subagent 规划自己的 work graph @@ -131,7 +131,7 @@ P2 已经设计了:`system/org-graph-templates/{dev,content,ops}.json` 模板å ### 阶段 7 · 全局 validator:整体判断 / 测试 / 审计 / benchmark / test data,失败则迭代 system agent 再 loop -> ⚠️ **v0.2 重要更正**:本节 v0.1 把 benchmark / test data 理解成了**系统级基础设施**,因此去核实 `benchmark-runner.js` / `benchmark.sqlite` 并判定"是假的、不存在"。**这个理解是错的。** 实际设计是:benchmark / test data / test script 是 **work graph 里的三个 agent 节点**(`task-benchmark` / `task-test-data` / `task-test-script`),由 planning agent 动态决定加哪几个。完整设计见 §十一。下面关于既有基础设施的核实结论仍然属实,但**它们与本流程无关**——本流程不使用 `benchmark-runner.js`。 +> ⚠️ **v0.2 重要更正**:本节 v0.1 把 benchmark / test data 理解成了**系统级基础设施**,因此去核实 `benchmark-runner.js` / `benchmark.sqlite` 并判定"是假的、不存在"。**这个理解是错的。** 实际设计是:benchmark / test data / test script 是 **work graph 里的三个 agent 节点**(`goal-benchmark` / `goal-test-data` / `goal-test-script`),由 planning agent 动态决定加哪几个。完整设计见 §十一。下面关于既有基础设施的核实结论仍然属实,但**它们与本流程无关**——本流程不使用 `benchmark-runner.js`。 **状态**:⚠️ 产出侧有清晰设计(§十一),**执行侧仍是空白**(产出验收标准 ≠ 执行验收标准) @@ -287,7 +287,7 @@ planner 阶段产出 benchmark/testdata/testscript,validator 阶段用它验æ” DevLoop 就这个问题做过显式决策(`loops-l2.md` 方案 A/B/C),选择"设计者写、执行者不写",明确否决"执行者自己写测试",理由是执行者会写出"永远会通过的 trivial test"。 -✅ **§十一 的三节点设计天然符合这条原则**:`task-benchmark` / `-test-data` / `-test-script` 三个 agent 与真正写代码的 coder 是**完全不同的 system agent**,产出者和被验收者分离,不存在"自己给自己出考题"的激励问题。 +✅ **§十一 的三节点设计天然符合这条原则**:`goal-benchmark` / `-test-data` / `-test-script` 三个 agent 与真正写代码的 coder 是**完全不同的 system agent**,产出者和被验收者分离,不存在"自己给自己出考题"的激励问题。 ⚠️ **但仍未解决"标准写错了"这一层**。缓解手段有两个,建议都要: 1. work graph 里的 `code-planner-validator` 节点承担一项明确职责——审"这套验收标准是否可度量、是否覆盖原始需求、是否存在平凡通过的漏洞",而不只是审 PRD/SDD 本身。 @@ -356,7 +356,7 @@ DevLoop 就这个问题做过显式决策(`loops-l2.md` 方案 A/B/C),选æ **所有 org graph / work graph 的 node agent,都由一个元 agent 架构继承生成,统一是「全局通用本体 + 公司/角色记忆分区」的结构。** -这条定案取代了 v0.1 §四 里"三个验收 agent 要不要按父节点特化"这个问题——答案是**不特化**:不存在 `task-benchmark` / `test-planner-benchmark` 各自独立的 agent,只有通用的 benchmark 设计能力,靠记忆分区区分它在不同 org node / 不同公司下的经验积累。agent 池不随 org node 数量膨胀,也与 [27-P1](./27-p1-virtual-reference.md) 虚拟引用寻址的初衷一致(同一份本体,多处引用,各自私有语境)。 +这条定案取代了 v0.1 §四 里"三个验收 agent 要不要按父节点特化"这个问题——答案是**不特化**:不存在 `goal-benchmark` / `test-planner-benchmark` 各自独立的 agent,只有通用的 benchmark 设计能力,靠记忆分区区分它在不同 org node / 不同公司下的经验积累。agent 池不随 org node 数量膨胀,也与 [27-P1](./27-p1-virtual-reference.md) 虚拟引用寻址的初衷一致(同一份本体,多处引用,各自私有语境)。 ✅ **元 agent 在仓库里已经存在**:`system/templates/base/`("标准基座员工 Base Agent")。它已经强制了一套四段式生命周期: @@ -434,9 +434,9 @@ benchmark / test data / test script **不是系统基础设施,是 work graph 例:`code-planner` 这个 org node 的 work graph 可能长成 ``` -brd-planning → prd-planning → sdd-planning ─┬→ task-benchmark ──┐ - ├→ task-test-data ──┼→ code-planner-validator → loop-validator - └→ task-test-script ┘ +brd-planning → prd-planning → sdd-planning ─┬→ goal-benchmark ──┐ + ├→ goal-test-data ──┼→ code-planner-validator → loop-validator + └→ goal-test-script ┘ ``` 三个验收节点之间**无依赖,可并行**(fan-out),汇合到 `code-planner-validator`(fan-in)。这正好是 §7.4 fan-out 能力的第一个真实用例。 @@ -450,8 +450,7 @@ brd-planning → prd-planning → sdd-planning ─┬→ task-benchmark ──â” ```jsonc { "version": "1", - "okr_node_id": "O-001.1.1", - "task_id": "T-xxx", + "goal_id": "GOAL-xxx", // 这份验收标准属于哪个 goal(一次人类需求) "benchmark": { "dimensions": [{"name":"...","weight":0.4,"pass_threshold":80}] } | null, "test_data": { "cases": [{"id":"...","input":{},"expect":{}}] } | null, "test_script": { "runner": "vitest", "path": "tests/acceptance.spec.js" } | null diff --git a/docs/todo/system-design/27-example-dev-company-walkthrough.md b/docs/todo/system-design/27-example-dev-company-walkthrough.md index c185a15..34988fa 100644 --- a/docs/todo/system-design/27-example-dev-company-walkthrough.md +++ b/docs/todo/system-design/27-example-dev-company-walkthrough.md @@ -124,17 +124,17 @@ node bin/lemon.js company hire --id auto-illust --role code-validator **规划结果**——注意三个验收节点是**动态选进来的**([27-E2E](./27-e2e-task-execution-flow.md) §十一): ``` -brd-planning → prd-planning → sdd-planning ─┬→ task-test-data ───┐ - └→ task-test-script ─┴→ code-planner-validator → loop-validator +brd-planning → prd-planning → sdd-planning ─┬→ goal-test-data ───┐ + └→ goal-test-script ─┴→ code-planner-validator → loop-validator ``` **planning agent 的选择理由**(这是它要在规划时说清楚的): | 验收节点 | 选/不选 | 理由 | |---|---|---| -| `task-test-script` | ✅ 选 | "按 H2 分段""输出 HTML"这些行为可以用代码断言真假 | -| `task-test-data` | ✅ 选 | markdown 输入空间复杂,需要正常/边界/异常样本(空文件、没有 H2、H2 嵌套) | -| `task-benchmark` | ❌ 不选 | 这一版图像 API 是 mock,没有"配图质量好不好"这种打分维度要评。**如果将来接真实图像 API,就要把这个节点加回来** | +| `goal-test-script` | ✅ 选 | "按 H2 分段""输出 HTML"这些行为可以用代码断言真假 | +| `goal-test-data` | ✅ 选 | markdown 输入空间复杂,需要正常/边界/异常样本(空文件、没有 H2、H2 嵌套) | +| `goal-benchmark` | ❌ 不选 | 这一版图像 API 是 mock,没有"配图质量好不好"这种打分维度要评。**如果将来接真实图像 API,就要把这个节点加回来** | 这正是"动态选择加哪几个"的实际含义——不是三个固定都跑。 @@ -143,8 +143,7 @@ brd-planning → prd-planning → sdd-planning ─┬→ task-test-data ──â” ```jsonc { "version": "1", - "okr_node_id": "O-001.1.1", - "task_id": "T-xxx", + "goal_id": "GOAL-xxx", // 这份验收标准属于哪个 goal(一次人类需求) "benchmark": null, // 本次没选这个节点 "test_data": { "cases": [ diff --git a/docs/todo/system-design/27-graph-agent-architecture.md b/docs/todo/system-design/27-graph-agent-architecture.md index 45a2ba8..a089efa 100644 --- a/docs/todo/system-design/27-graph-agent-architecture.md +++ b/docs/todo/system-design/27-graph-agent-architecture.md @@ -172,6 +172,7 @@ CREATE TABLE work_graphs ( id TEXT PRIMARY KEY, company_id TEXT NOT NULL, triggered_by_org_node_id TEXT REFERENCES org_graph_nodes(id), + goal_id TEXT, -- 一次人类需求描述(唯一,验收边界) okr_node_id TEXT, -- 形如 O-001.1.1,配合 company_id 定位 task_id TEXT, -- 形如 T-xxx status TEXT NOT NULL DEFAULT 'planning', -- planning | running | passed | failed | blocked diff --git a/docs/todo/system-design/27-naming-conventions.md b/docs/todo/system-design/27-naming-conventions.md index 2cca88c..85dd0ba 100644 --- a/docs/todo/system-design/27-naming-conventions.md +++ b/docs/todo/system-design/27-naming-conventions.md @@ -23,7 +23,8 @@ | `orggraph` | 公司级 workflow | | `workgraph` | org node 级 workflow | | `{domain}` | 业务领域(`code` / `content` / `ops` …),即 org node 所属领域 | -| `task` | 单个任务 | +| `goal` | **一个人类需求描述**(唯一,验收边界)| +| `task` | 图中的执行单元(一个 goal 分解出多个,可并行)| | `agent` | 单个 system agent | | `skill` | 单个 skill | @@ -58,23 +59,29 @@ org graph 上的节点 agent,一律带领域前缀: --- -## 四、验收产物 —— `task-{类型}` +## 四、验收产物 —— `goal-{类型}` work graph 内动态选入的验收产出节点(见 [27-E2E](./27-e2e-task-execution-flow.md) §十一): | id | 产出 | |---|---| -| `task-benchmark` | 打分式验收标准(维度 + 权重 + 及格线) | -| `task-test-data` | 输入样本集(正常 / 边界 / 异常) | -| `task-test-script` | 可执行断言脚本 | +| `goal-benchmark` | 打分式验收标准(维度 + 权重 + 及格线) | +| `goal-test-data` | 输入样本集(正常 / 边界 / 异常) | +| `goal-test-script` | 可执行断言脚本 | -### 为什么是 `task-` 而不是 `goal-` +### 为什么是 `goal-` 而不是 `task-` -原本的理由是"`goal` 被 OKR 体系占用",但 §六 决定把 OKR 体系从 `goal` 改名为 `okr`,**这个撞名理由已经不成立**。改用 `task-` 的理由现在只剩一条,但它本身足够: +**关键区分是基数**: -**验收标准的生命周期跟着一次 task 执行走** —— 由该 task 的 `{domain}-planner` 阶段产出、该 task 的 `{domain}-validator` 阶段消费、task 结束即归档。而 OKR 里的 Key Result 是**跨多个 task、长周期的度量目标**,两者时间尺度不同。用 `task-` 与它的真实作用域一致。 +| 概念 | 基数 | 定义 | +|---|---|---| +| **goal** | 一个人类需求描述 = **1 个** | 验收的边界。回答"这次交付到底算不算满足了人提的要求" | +| **task** | 一个 goal 分解出 **N 个** | 图中的执行单元。可并行、可下钻 sub agent,一个 goal 在图里会有很多个 | +| **okr** | 跨多个 goal 的长周期度量树 | Objective / Key Result,见 §六 | + +验收标准回答的是"**人类想要的东西做到了没有**"——这是 goal 级的判定。task 只是达成它的执行分支,一个 goal 下有很多个;把验收挂在 task 上会导致"到底以哪个 task 的验收为准"根本无法回答。 -> `goal-` 现在是空闲的,如果更偏好那个词,全局换一下即可,不影响任何其他设计。 +> **决策沿革**(完整过程见 [27-REQ](./27-requirement.md) R-10 / R-12):最初选 `task-`,理由是"`goal` 被 OKR 占用";§六 把 OKR 正名后该理由失效,改用"验收跟着一次 task 执行走"继续保留 `task-`;最终因上面的基数论证推翻,定为 `goal-`。 --- @@ -86,7 +93,7 @@ work graph 内动态选入的验收产出节点(见 [27-E2E](./27-e2e-task-exe |---|---|---| | **`skill-benchmark`** | 给 **Skill** 打分 + Arena ELO 排行榜 | ✅ 已实现:`server/services/benchmark-runner.js`、`benchmark-db.js`、`benchmark_runs` 表(主键 `skill_name`)、`comparisons` ELO 表、路由 `/benchmarks` `/benchmark-all` `/benchmark/status` | | **`agent-benchmark`** | 给**单个 system agent** 打能力分,用于 hire / `depositTemplate()` 的 **≥95 门槛** | ⚠️ 部分存在:`system_agents.benchmark_score` 字段(P0 已落地)、`_registry.json` 的 `benchmarkScore`(实测仅 3 条非空:ceo=97 / qa-judge=95 / base=90) | -| **`task-benchmark`** | 给**单个任务**定验收标准,由 `task-benchmark` agent 产出、validator 节点执行 | 🔴 本次设计新增,尚未实现 | +| **`goal-benchmark`** | 给**单个 goal**(一次人类需求描述)定验收标准,由 `goal-benchmark` agent 产出、validator 节点执行 | 🔴 本次设计新增,尚未实现 | ### 代码层重命名的影响面(未执行,需单独排期) @@ -99,12 +106,14 @@ work graph 内动态选入的验收产出节点(见 [27-E2E](./27-e2e-task-exe | `/benchmarks` `/benchmark-all` `/benchmark/status` | `server/routes/` | 公开 API,改路径破坏外部调用方 | | `benchmark-runner.js` / `benchmark-db.js` | `server/services/` | 文件重命名成本低,但所有 require 点要同步 | -**建议**:代码层保持现状(既有的就默认是 `skill-benchmark` 语义),**只对新增代码强制用新前缀**。即 `task-benchmark` 相关的表、字段、路由从第一天就带前缀,不与既有的混在一起。等哪天真要清理历史命名时,再按上表单独排期。 +**建议**:代码层保持现状(既有的就默认是 `skill-benchmark` 语义),**只对新增代码强制用新前缀**。即 `goal-benchmark` 相关的表、字段、路由从第一天就带前缀,不与既有的混在一起。等哪天真要清理历史命名时,再按上表单独排期。 --- ## 六、OKR 体系:从 `goal` 改名为 `okr` +> ⚠️ **注意与 §四 的区别**:本节说的是**把 OKR 体系/树/节点从 `goal` 这个词里解放出来**。解放之后 `goal` 被重新赋予 §四 的新含义 ——「一个人类需求描述」。两者不冲突,但读的时候要分清:`okr` 是跨多个 goal 的长周期度量树,`goal` 是一次具体的人类需求。 + 这棵树的正式名称是 **OKR(Objective - Key Result)**,不应该叫 "goal"。当前代码里 `goal` 既是树的名字、又是树里第 1 层节点的名字,是一处自我遮蔽的命名。 ### 现状层级 @@ -162,8 +171,8 @@ task_id TEXT, -- 形如 'T-xxx',system/tasklog/{taskId}.json | `validator` | `code-validator` / `content-validator` / … | | `planning` | `orggraph-planning` / `workgraph-planning` / `brd-planning` / `prd-planning` / `sdd-planning` | | `org-graph-creator` | `orggraph-planning` | -| `benchmark`(裸用) | `skill-benchmark` / `agent-benchmark` / `task-benchmark` | -| `test-data` / `test-script`(裸用) | `task-test-data` / `task-test-script` | +| `benchmark`(裸用) | `skill-benchmark` / `agent-benchmark` / `goal-benchmark` | +| `test-data` / `test-script`(裸用) | `goal-test-data` / `goal-test-script` | | `goal` / `goals`(指 OKR 体系时) | `okr` | | `Goal`(指 OKR 第 1 层节点) | `Objective`(或 `Mission`,若保留四层) | | `goalId` | `okrNodeId` | diff --git a/docs/todo/system-design/27-p3-p4-work-graph-console.md b/docs/todo/system-design/27-p3-p4-work-graph-console.md index c42e2d8..d05b8b7 100644 --- a/docs/todo/system-design/27-p3-p4-work-graph-console.md +++ b/docs/todo/system-design/27-p3-p4-work-graph-console.md @@ -99,6 +99,7 @@ CREATE TABLE IF NOT EXISTS work_graphs ( company_id TEXT NOT NULL, triggered_by_org_node_id INTEGER REFERENCES org_graph_nodes(id), -- 对应"每个 org node 运行的 work graph" parent_node_id TEXT REFERENCES work_graph_nodes(id), -- 非空 = 这是另一个节点下钻出来的嵌套子图(§四.D.3) + goal_id TEXT, -- 一次人类需求描述(唯一,验收边界) okr_node_id TEXT, -- 形如 O-001.1.1 task_id TEXT, -- 形如 T-xxx execution_mode TEXT NOT NULL DEFAULT 'manual' CHECK (execution_mode IN ('manual','auto')), diff --git a/docs/todo/system-design/27-requirement.md b/docs/todo/system-design/27-requirement.md index dfe001d..ac50ad1 100644 --- a/docs/todo/system-design/27-requirement.md +++ b/docs/todo/system-design/27-requirement.md @@ -39,7 +39,7 @@ > org graph 生成,应该由 company 的第一个 agent: org graph creator agent 来实现,根据这个公司的目标,描述,类型,来生成,比如要生成开发,还是运营,还是内容生成,会有多个不同的 org graph的模板,然后根据需求+agent list 动态来生成 org graph **落点**:[27-P2](./27-p2-org-graph.md) §4.1(`orggraph-planning` agent)、§4.6(`system/org-graph-templates/`) -**后续变更**:其中 `org graph creator` 这个名字在 R-12 的命名统一中改为 `orggraph-planning`。 +**后续变更**:其中 `org graph creator` 这个名字在 R-10 的命名统一中改为 `orggraph-planning`。 --- @@ -81,7 +81,7 @@ **这条更正推翻了什么**:此前我把 benchmark / test data 理解成系统级基础设施,因而去核实 `benchmark-runner.js` 并判定「是假的、test data 不存在」。该判断与本需求无关——本流程根本不使用 `benchmark-runner.js`。 -**后续变更**:文中的 `code-planner-benchmark` / `code-planner-test-data` / `code-planner-test-script` 三个名字,在 R-12 的命名统一中改为 `task-benchmark` / `task-test-data` / `task-test-script`(作用域从"父节点"改为"任务")。 +**后续变更**:文中的 `code-planner-benchmark` / `code-planner-test-data` / `code-planner-test-script` 三个名字,经 R-10 与 R-12 两轮,最终定为 `goal-benchmark` / `goal-test-data` / `goal-test-script`(作用域从"父 org node"改为"goal")。 --- @@ -138,7 +138,7 @@ **落点**:[27-P2 v0.4](./27-p2-org-graph.md) 全文重写、[27-NAMING](./27-naming-conventions.md) 全文 -**一处需要留意的取舍**:原话给了 `goal-benchmark` 或 `task-benchmark` 两个选项,最终选 `task-`。当时的理由是"`goal` 已被 OKR 体系占用",但 R-11 决定把 OKR 从 `goal` 改名后,这个理由已不成立;保留 `task-` 的理由改为"验收标准的生命周期跟着一次 task 执行走,而 OKR 的 Key Result 是跨多个 task 的长周期度量"。**`goal-` 目前是空闲的,若要改回,全局换一个词即可。** +**取舍过程**:原话给了 `goal-` 与 `task-` 两个选项。我初次选了 `task-`,理由是"`goal` 已被 OKR 体系占用";R-11 把 OKR 正名后该理由失效,我改用"验收标准跟着一次 task 执行走"作为理由继续保留 `task-`。**这个理由在 R-12 被推翻,最终定为 `goal-`。** --- @@ -152,6 +152,24 @@ --- +## R-12 · 验收产物定名 `goal-`,并给出 goal 与 task 的层级区分 + +> 改回 goal-benchmark,因为 task 可能有很多个,task 是 sub agent 或者并行的层次,但是 goal 对于一个人类的需求描述只有一个,task 在 graph 中可能会有多个 + +**落点**:[27-NAMING](./27-naming-conventions.md) §四(含 goal / task / okr 三者的层级定义) + +**这条推翻了什么**:推翻了 R-10 阶段"验收标准跟着一次 task 执行走"这个理由。**关键区分是基数**: + +| 概念 | 基数 | 说明 | +|---|---|---| +| **goal** | 一个人类需求描述 = **1 个** | 验收的边界。"这次交付到底算不算满足了人的要求" | +| **task** | 一个 goal 分解出 **N 个** | 图中的执行单元,可并行、可下钻 sub agent | +| **okr** | 跨多个 goal 的长周期度量树 | Objective / Key Result(见 R-11) | + +验收标准回答的是"人类想要的东西做到了没有",这是 goal 级的判定;task 只是达成它的执行分支,一个 goal 下有很多个,把验收挂在 task 上会导致"到底以哪个 task 的验收为准"无法回答。 + +--- + ## 附 · 需求 → 设计落点 速查 | 需求 | 一句话 | 主要落点 | @@ -167,3 +185,4 @@ | R-9.4 | L4 拆 company(自动)/ general(dream,人工或 master 驱动) | E2E §八 / §8.1 | | R-10 | 统一命名前缀 | NAMING 全文 | | R-11 | OKR 正名,不叫 goal | NAMING §六 | +| R-12 | **验收产物定名 `goal-`**;goal 唯一、task 多个 | NAMING §四 | -- libgit2 0.21.4