plan.md
5.44 KB
P0 地基 — Graph Agent 架构任务拆分
对应
docs/system-design/27-graph-agent-architecture.md的 Phase P0。目标:只加不改——新建三张表,把现有数据原样导入作为种子数据并校验行数,完全不动company-service.js现有的 hire/copy 执行路径。这是 P1(虚拟引用改造)能安全推进的前提:先有一份可信、经过校验的镜像数据在 DB 里,再去改代码。
Context
两轮只读调研确认了关键事实:
- 现有三个 sqlite 库(
skills.sqlite/benchmark_logs.sqlite/users.sqlite)都遵循同一套手写约定:server/services/*-db.js里new Database()+ WAL +CREATE TABLE IF NOT EXISTS(无迁移文件、无版本追踪),snake_case 列名。没有:memory:测试,测试用临时文件 + env 变量覆盖 DB 路径 + 清 require 缓存(server/tests/unit/skill-db.test.js是标准范式)。benchmark-db.js声明了 env override 但实际没读,是个已知的潜在 bug,新代码要避免重蹈。 system/agents/有 11 个目录,其中system/agents/templates/是遗留杂物、不是真 agent,必须过滤掉(真实 agent 数 = 10)。system/templates/有 34 个目录,但_registry.json(数组)只覆盖 9 个(ceo/qa-judge/base/6 个 devloop-*)——目录扫描才是数据源头,registry 只用来补充可选的 benchmark 元数据,其余 25 个模板要容忍没有config.json(如ceo/只有plan.md+todo.md)。data/companies/目前只有一家真实公司idearun,company.json.agents是 6 个角色名字符串的扁平数组:youtube-crawler/evolver-youtube-crawler能对上system/agents/里的全局 agent,另外 4 个(claude-youtube-skills/trend-scout-global/content-selector/idearuncreate)在 global/template 里都找不到对应目录——这些是公司专属训练出来的实例,是"company-scoped system agent"这个概念在真实数据里的第一批样本。company-service.js的hire(189)/scaffoldNewAgent(241)/depositTemplate(294)/hireWithTraining(381)/_copyTemplate(621)/_injectCompanyContext(667) 六个函数行号已核实无漂移,P0 全程不动这个文件。
新增文件
server/services/graph-db.js—— 新 sqlite 库data/graph.sqlite,照抄skill-db.js/user-db.js的样板:fs.mkdirSync保证目录存在 →new Database(DB_PATH)→journal_mode=WAL+foreign_keys=ON→ lazy singletongetDb()。支持GRAPH_DB_PATHenv 覆盖,且要确保代码真的读了这个变量。server/services/graph-seed-service.js—— 导出seedGlobalAgents()/seedTemplates()/seedCompanyAgents()/verifyCounts(),供脚本和测试复用。scripts/graph-seed.js—— 薄 CLI 入口,依次调用上面四个函数并打印汇总报告,风格参照现有scripts/sync-skills.js。package.json加一条"graph:seed": "node scripts/graph-seed.js"。server/tests/unit/graph-db.test.js—— 照抄skill-db.test.js的临时文件 + env 覆盖 + 清 require 缓存范式。
Schema
CREATE TABLE IF NOT EXISTS system_agents (
id TEXT PRIMARY KEY, -- 就是目录名,如 'master'/'ceo'/'claude-youtube-skills'
name TEXT NOT NULL,
scope TEXT NOT NULL CHECK (scope IN ('public','company')),
owner_company_id TEXT,
source_kind TEXT NOT NULL CHECK (source_kind IN ('global_agent','template','company_hired')),
legacy_path TEXT NOT NULL, -- 当前真实所在目录,如 'system/agents/master'
status TEXT NOT NULL DEFAULT 'active',
benchmark_score REAL,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS org_graph_nodes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id TEXT NOT NULL,
system_agent_id TEXT NOT NULL REFERENCES system_agents(id),
role_name TEXT NOT NULL,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS org_graph_edges (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id TEXT NOT NULL,
from_node_id INTEGER NOT NULL REFERENCES org_graph_nodes(id),
to_node_id INTEGER NOT NULL REFERENCES org_graph_nodes(id),
relation_type TEXT NOT NULL
);
相对设计文档(27 号)草稿的两处调整:
system_agents.id用 TEXT PRIMARY KEY = 目录名,不用自增代理键——后续阶段要靠这个 id 反查文件系统路径,代理键只会多一层无意义的间接。- 新增
source_kind+legacy_path两列——P0 明确不做目录搬迁(三种来源现在物理上分散在三个不同地方),没有这两列种子数据就"没有指针",没法在 P1 真正切换执行路径时定位到原文件。
org_graph_nodes/org_graph_edges 沿用仓库现有的自增整数主键惯例,暂不需要对外暴露的字符串 ID(要到 P2/P3 才会被外部引用)。
验证方式
npm run test:unit—— 新增的graph-db.test.js通过,现有测试无回归npm run graph:seed—— 在真实仓库数据上跑,人工核对输出的行数汇总(10 / 34 / 6,见下方任务列表)sqlite3 data/graph.sqlite ".schema"—— 人工确认三张表结构与上面 SQL 一致git diff --stat—— 确认这一阶段的改动只新增文件,没有改动company-service.js/agent-manager.js/prompt-builder.js任何一行
任务清单见 todo.md。