27-NAMING · Graph Agent 体系命名规范
所属: 27 Graph Agent 架构 的跨文档命名约定。 版本: v0.2(§六 OKR 正名已落地到代码层,见该节执行结果表) 日期: 2026-08-15 适用范围: 27 系列全部文档 + 后续实现中新建的 system agent id、表名、字段名、API 路径。 为什么需要这份文档: 本体系引入的概念(planner / validator / planning / benchmark)在仓库里全部已经有同名但不同义的既有占用。不先统一,日后 grep 和排查会持续付出代价。
一、总规则
{作用域}-{职能}
任何 agent id、验收产物类型、评测体系名,都必须带作用域前缀,不允许裸用 planner / validator / planning / benchmark。
作用域从大到小:
| 作用域 | 含义 |
|---|---|
orggraph |
公司级 workflow |
workgraph |
org node 级 workflow |
{domain} |
业务领域(code / content / ops …),即 org node 所属领域 |
company-goal |
公司的目标(建公司时写入,OKR 树的输入) |
task-goal |
一次用户请求的目标(唯一,验收边界;R-12 说的就是这一层) |
subtask-goal |
子任务的目标(一个 task-goal 分解出多个) |
task |
图中的执行单元(一个 task-goal 分解出多个,可并行) |
agent |
单个 system agent |
skill |
单个 skill |
二、规划类 agent —— {产出物}-planning
| id | 职责 | 所在层级 |
|---|---|---|
orggraph-planning |
根据公司目标/描述,生成公司级 workflow(org graph) | company,建公司时跑一次 |
workgraph-planning |
根据任务,为某个 org node 生成该节点的 workflow(work graph) | org node,每次接到任务时 |
brd-planning |
产出 BRD | work graph 内的节点 |
prd-planning |
产出 PRD | work graph 内的节点 |
sdd-planning |
产出 SDD | work graph 内的节点 |
⚠️ 重命名:27-P2 v0.2/v0.3 里叫 org-graph-creator 的 agent,统一改名为 orggraph-planning。v0.4 起全文使用新名。
三、图节点 agent —— 按所在图的层级命名(R-15.3 定案)
命名轴是节点在哪一层图里,不是它属于哪个业务领域。
3.1 两层节点名
| 层级 | 节点名规则 | 例 |
|---|---|---|
| Org Graph 节点 | org-{职能} |
org-planner / org-coder / org-validator / org-innovator |
| Work Graph 节点 | {父 org 节点全名}-{职能} |
org-coder-validator / org-planner-validator |
三个 org-graph 模板因此首尾同名,只有中段职能不同——差异在于中间做什么,规划和验收本身不分领域:
dev.json org-planner → org-coder → org-validator
content.json org-planner → org-writer → org-validator
ops.json org-planner → org-monitor → org-validator
为什么不按业务领域(v0.2 曾定为 code-planner / content-planner,已作废):一家公司的 org graph 只有一套节点,领域信息由 company 本身承载。同一个 org-planner 服务开发型还是内容型公司,靠 27-E2E §八bis 的元 agent 继承 + 公司/角色记忆分区区分行为。按领域命名会让 agent 池随「领域数 × 职能数」膨胀,同一种能力无法跨领域复用经验。
3.2 节点名 ≠ 本体名(R-15.3 新增的命名轴)
这是本规范此前完全缺失的一条轴,不区分会直接导致 agent 本体被无谓复制:
| 例 | 带前缀? | |
|---|---|---|
| system agent 本体 | planner-validator / coder-validator / org-validator |
❌ 不带 |
| org graph 节点 | org-planner / org-coder / org-validator |
✅ 带 org- |
| work graph 节点 | org-coder-validator / org-planner-validator |
✅ 带父节点全名 |
落到 schema 上就是两个字段(27-P3/P4 §四.A):node_name 存节点名(图内唯一),system_agent_id 存本体名(跨图复用)。
为什么本体不带前缀:禁止裸用 validator 的理由是「一家公司内两个节点不能重名」——该理由针对节点,不针对本体。本体若被迫带领域前缀,coder-validator 会复制成 org-coder-validator / content-coder-validator 多份,与 27-P1「同一份本体、多处引用、各自私有语境」直接冲突。
3.3 三个 validator 是三个独立本体
planner-validator / coder-validator / org-validator 验的东西本质不同——规划产物 / 代码 / 整个任务达成,是不同能力,不是同一能力的不同语境。§八bis 的「不特化」原则针对的是同一能力在不同 org node 下,与本条不冲突。
两级验收的分工:
| 节点名 | 验什么 | 失败退到哪 | |
|---|---|---|---|
| org 层 | org-validator |
整个任务达成了吗 | 退回某个 org node,整张 work graph 重跑 |
| work 层 | org-{X}-validator |
这个 org node 自己的产出合格吗 | 退回本张 work graph 内的某个节点 |
org-validator 本身是一个 org node,按定义有自己的 work graph,benchmark-validator / testdata-validator 就是这张 work graph 的节点——落在已有的递归模型里,引擎不加分支。
3.4 存量 system agent 的归位
按同一规则把散落的老 agent 归到它实际所处的层级:
| 旧名 | 新名 | 依据 |
|---|---|---|
innovator |
org-innovator |
type='cxo',是 org graph 层的节点 |
hunter |
innovator-hunt |
retrain-pipeline.js:161,innovator work graph 第 1 阶段 |
digester |
innovator-digest |
同上第 2 阶段(行 179,输入是 hunter 产出) |
evolver |
innovator-evolver |
同上第 3 阶段(行 196);行 231 明写 steps: ['re_hunt','re_digest','evolve'] |
这顺带解决了 6 个命名冲突 id(27 号文档 §七)——重命名后 system/agents/ 与 system/templates/ 下不再有同名目录。剩两个单独判断:
agent-creator:与orggraph-planning同属基础设施角色,不是任何图上的节点,不加前缀,保持原名。evolver-youtube-crawler:针对单个 skill 特化的 evolver 实例,按规则应为innovator-evolver-youtube-crawler,名字过长且疑似一次性产物,待定,暂不改名。
✅ §3.4 的四个重命名已落到代码(
scripts/migrate-agent-naming.js,幂等可重跑): 8 个目录(system/agents/+system/templates/)、system_agents表 4 行、 以及 5 处代码引用点(retrain-pipeline.js的agent:字段 /agentToStep映射 /call_sub_agent判断、agent-chat.js的 agent 列表过滤、company.js的训练触发)。迁移时明确不动的东西(改了会坏):
- skill 内部子目录名
{skillDir}/hunter/knowhow.md—— 那是 hunt/digest/evolve 三阶段的产物目录约定,与 agent 名同形但不同义- skill 命名空间的白名单(
skill-dir-manager.js的CORE_SKILLS、migrate-trained-skills.js的SYSTEM_SKILLS)—— 那里的innovator指同名 skillconversations/与system/tasklog/下的历史记录 —— 运行态数据,不改写历史
3.5 归因类节点 —— validator-triager(R-16 立项,R-17.2 定名)
R-16 把「失败该怪谁」从 validator 手里拆出来,交给一个专职的归因节点:org-validator 自己的 work graph 里
第一个节点就是它,产出 fail_reason + remediation_note,透传回 org 层作为选边依据
(见 27-P3/P4 §四.D.2.2 / §四.D.3)。
按本节的命名轴,它是work graph 层的节点——它活在 org-validator 这个 org node 的 work graph 里,
不是 org graph 上的节点,因此不带 org- 前缀,而是随父节点得名。
✅ 职能词已定案为 triager(27-REQ R-17.2)。理由:它做的是归因不是判定,
triager 与 DevLoop 已经跑通的 BugTriager 同构,语义更准。
validator-reflection 是历史名,除 R-16 正文的原话引用(照搬原则,不改)外,一律不再使用。
⚠️ 仍有一处未定案:前缀取父节点全名还是职能:
| # | 待定案 | 两个选项 | 现状 |
|---|---|---|---|
| 1 | 前缀取父节点全名还是职能 | §3.1 的规则写的是 {父 org 节点全名}-{职能} → org-validator-triager;27-P3/P4 全文用的是父节点职能的简写 → validator-triager |
暂用简写 validator-triager,与 §3.1 的字面规则存在出入,定案前不要以任一方去改另一方 |
reflection 还是 triager |
已定案 triager(R-17.2),见上 |
同一层的其它 work graph 节点(
benchmark-validator/testdata-validator等)不受这处待定案影响, 它们在 §3.2 里已经明确是本体名,本来就不带前缀。🔁 改名的影响面(R-17.2 落地范围):
system/templates/validator-triager/(目录 + 内容自称)、system/templates/_registry.json条目、system/templates/org-validator/的节点名引用、system/work-graph-templates/validator.json的nodeName/systemAgentId/ 边端点、 本文档本节、27-P3/P4 全文,以及graph-engine.js的ATTRIBUTION_NODE_NAME常量与node.reflectiontimeline 事件名(引擎侧另行改)。 这七处必须同时改——节点名与systemAgentId与引擎常量三者只要有一处不同步, 归因产出就会静默落不到透传路径上(27-P3/P4 §十 的「四环漏一环」缺陷模式)。
四、验收产物 —— goal-{类型}
work graph 内动态选入的验收产出节点(见 27-E2E §十一):
| id | 产出 |
|---|---|
goal-benchmark |
打分式验收标准(维度 + 权重 + 及格线) |
goal-test-data |
输入样本集(正常 / 边界 / 异常) |
goal-test-script |
可执行断言脚本 |
为什么是 goal- 而不是 task-
关键区分是基数:
| 概念 | 基数 | 定义 |
|---|---|---|
| goal | 一个人类需求描述 = 1 个 | 验收的边界。回答"这次交付到底算不算满足了人提的要求" |
| task | 一个 goal 分解出 N 个 | 图中的执行单元。可并行、可下钻 sub agent,一个 goal 在图里会有很多个 |
| okr | 跨多个 goal 的长周期度量树 | Objective / Key Result,见 §六 |
验收标准回答的是"人类想要的东西做到了没有"——这是 goal 级的判定。task 只是达成它的执行分支,一个 goal 下有很多个;把验收挂在 task 上会导致"到底以哪个 task 的验收为准"根本无法回答。
goal 是三层递归的(R-13)
「goal」本身在三个层级上各有一个,与 27-E2E §11.3「验收逐层递归」严格对应——每一层的 goal 就是那一层的验收边界:
| goal | 归属 | 谁验收它 | 落在哪 |
|---|---|---|---|
company-goal |
公司 | OKR 树(长周期度量) | company.json.goal,建公司时写入 |
task-goal |
一次用户请求 | org graph 末端的 org-validator |
任务入口带入 |
subtask-goal |
子任务 / 并行分支 | 该 work graph 内的 validator 节点 | 由 workgraph-planning 拆分时产生 |
company-goal 与 OKR 的关系:company-goal 是建公司时的一句话定性目标,是 OKR 树的输入——OKR 把它拆成可度量的 Objective → Key Result。两者不是替代关系,不要用 OKR 节点去存 company-goal。
三个验收 agent(goal-benchmark / goal-test-data / goal-test-script)是通用的,不按层级拆分:它们在哪一层被调用,就为那一层的 goal 产出验收标准。这与 §八bis 的元 agent 继承(全局通用本体 + 记忆分区)一致——不需要 task-goal-benchmark / subtask-goal-benchmark 这种按层级复制的 agent。
命名轴已统一(R-14):三者一律按作用域命名 ——
company-goal/task-goal/subtask-goal。最初提出时第三个叫subagent-goal(按执行者命名,与另两个的轴不一致),已统一为subtask-goal。原话见 27-REQ R-13.1。决策沿革(完整过程见 27-REQ R-10 / R-12):最初选
task-,理由是"goal被 OKR 占用";§六 把 OKR 正名后该理由失效,改用"验收跟着一次 task 执行走"继续保留task-;最终因上面的基数论证推翻,定为goal-。
五、三种 benchmark 必须分开(当前全部叫 benchmark)
仓库里 benchmark 一词同时指三件完全不同的事。统一加前缀区分:
| 新名 | 指什么 | 现状 |
|---|---|---|
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) |
goal-benchmark |
给单个 goal(一次人类需求描述)定验收标准,由 goal-benchmark agent 产出、validator 节点执行 |
🔴 本次设计新增,尚未实现 |
代码层重命名的影响面(未执行,需单独排期)
文档层的消歧已在 27 系列全部完成。代码层的重命名是一次真实的数据迁移,不是 find-replace,因此本轮只给出影响面清单,不动代码:
| 对象 | 位置 | 风险 |
|---|---|---|
benchmark_runs / comparisons / security_scans 表 |
data/benchmark.sqlite |
改表名需迁移脚本 + 停机;这三张表服务于线上 Arena 排行榜 |
benchmarkScore 字段 |
system/templates/_registry.json(磁盘数据) |
改字段名需同步改所有读写方 + 迁移已有数据 |
/benchmarks /benchmark-all /benchmark/status |
server/routes/ |
公开 API,改路径破坏外部调用方 |
benchmark-runner.js / benchmark-db.js |
server/services/ |
文件重命名成本低,但所有 require 点要同步 |
建议:代码层保持现状(既有的就默认是 skill-benchmark 语义),只对新增代码强制用新前缀。即 goal-benchmark 相关的表、字段、路由从第一天就带前缀,不与既有的混在一起。等哪天真要清理历史命名时,再按上表单独排期。
六、OKR 体系:从 goal 改名为 okr
⚠️ 注意与 §四 的区别:本节说的是把 OKR 体系/树/节点从
goal这个词里解放出来。解放之后goal被重新赋予 §四 的新含义 ——「一个人类需求描述」。两者不冲突,但读的时候要分清:okr是跨多个 goal 的长周期度量树,goal是一次具体的人类需求。
这棵树的正式名称是 OKR(Objective - Key Result),不应该叫 "goal"。当前代码里 goal 既是树的名字、又是树里第 1 层节点的名字,是一处自我遮蔽的命名。
层级改动(已实施)
迁移前:
G-001 → Goal (第1层)
G-001.1 → Objective (第2层)
G-001.1.1 → Key Result (第3层)
G-001.1.1.1 → Sub-Task (第4层+)
迁移后:
O-001 → Objective (第1层)
O-001.1 → Key Result (第2层)
O-001.1.1 → Sub-Task (第3层+)
改法
体系整体叫 OKR,第 1 层的 "Goal" 也一并正名 —— OKR 的标准词汇里没有 "Goal" 这一层,现在的第 1 层实际承担的是"一个大目标下挂多组 OKR"的容器角色:
| 层 | 旧名 | 新名 | ID 前缀 |
|---|---|---|---|
| 1 | Goal | Objective(顶层目标) | O-001 |
| 2 | Objective | Key Result | O-001.1 |
| 3 | Key Result | Sub-Task | O-001.1.1 |
| 4+ | Sub-Task | (合并进 Sub-Task 层级) | O-001.1.1.1 |
这样是标准的 Objective → Key Result → Sub-Task 三层。如果确实需要保留四层,则第 1 层建议叫 Mission(
M-001),下挂 Objective / Key Result / Sub-Task —— 但不要再叫 Goal。
影响面与执行结果(✅ 已实施)
v0.2 更正:本节初版把磁盘数据迁移标为「高风险」,那是高估。实地核实后,存量数据几乎为空:
data/goals/_index.json与data/companies/idearun/goals/_index.json都是[],data/goals/G-001/只剩一个孤儿history.log(goal.json早已丢失),system/tasklog/完全为空。真实风险是低的。
| 对象 | 处理 | 状态 |
|---|---|---|
server/services/goals.js → okr-service.js;GoalsService → OkrService |
git mv + 标识符改名 | ✅ |
server/routes/goals.js → okr.js |
git mv | ✅ |
/api/goals/* → /api/okr/* |
index.js / agent-server.js 同时注册新旧两条路径,旧路径作为向后兼容别名 |
✅ |
/api/company/:cid/goals/* → /okr/*(7 条) |
用数组路径 [/:companyId/okr...,/:companyId/goals...] 一次挂两个 URL |
✅ |
data/{,companies/*/}goals/ → okr/ |
scripts/migrate-goals-to-okr.js(npm run okr:migrate) |
✅ |
ID 前缀 G- → O-;goal.json → objective.json |
同上脚本,含 nodes 的 key、children 数组、_index.json、progress.json、history.log |
✅ |
层级名 ['Goal','Objective','KeyResult','SubTask'] → ['Objective','KeyResult','SubTask','SubTask'] |
parseNodeId() |
✅ |
goalId 请求体字段 |
agent-chat.js 的 dispatch/report 同时接受 objectiveId(新)与 goalId(旧),写入时两个字段都留 |
✅ |
OkrDashboard.vue / CompanyDashboard.vue |
切到 /api/okr |
✅ 前后端命名终于一致 |
bin/lemon.js |
新增 okr create/add-node/list/status,保留 goal * 作为别名 |
✅ |
迁移脚本要点(scripts/migrate-goals-to-okr.js):
--dry-run预演;幂等可重复执行;迁移前自动备份为*.bak-goals- 处理一个反直觉的边界:
OkrService构造函数会自动mkdir目标目录,所以「okr/已存在」不等于「已迁移过」——只要服务被 require 过一次就会留下空壳。脚本用isEmptyOkrDir()区分空壳与真实数据,空壳直接移除后继续迁移。 - 容忍孤儿条目(有
history.log无goal.json)
验证:server/tests/unit/okr-service.test.js(7 例)+ 全量 npm run test:unit(652 例全绿)。
对 27 系列的直接影响
27-E2E §三 阶段 3 指出:27 号文档 work_graphs.goal_task_id 这个单字段不足以定位一个 OKR 节点(需要 companyId + 树 ID + 节点 ID 三元组)。改名后该字段应为:
okr_node_id TEXT, -- 形如 'O-001.1.1',配合 company_id 定位
task_id TEXT, -- 形如 'T-xxx',system/tasklog/{taskId}.json
七、速查表
| 不要用 | 要用 |
|---|---|
planner |
org-planner(节点) |
validator |
节点:org-validator / org-{X}-validator;本体:org-validator / {X}-validator |
planning |
orggraph-planning / workgraph-planning / brd-planning / prd-planning / sdd-planning |
code-planner / code-coder / code-validator |
org-planner / org-coder / org-validator |
content-planner / content-writer / content-validator |
org-planner / org-writer / org-validator |
ops-planner / ops-monitor / ops-validator |
org-planner / org-monitor / org-validator |
org-graph-creator |
orggraph-planning |
innovator |
org-innovator |
hunter |
innovator-hunt |
digester |
innovator-digest |
evolver |
innovator-evolver |
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(OKR 树根 ID) |
objectiveId |
nodeId(树内节点) |
nodeId(不变,已由 objectiveId 限定作用域) |
G-001.1.1 |
O-001.1.1 |